直接回答:先判断旧字段是否还能承载历史数据。如果旧字段语义正确、只是数量不够,就保留旧字段并新增字段;如果旧字段语义已经错位,例如把“备注”当“状态”用,就应停止继续写入并迁移到新字段;只有当旧字段被大量外部系统直接依赖且无法改接时,才考虑退出旧结构、另建一张扩展表。判断依据不是字段数量,而是旧字段是否仍能被准确解释。
当旧字段的名称和含义仍然成立,只是需要更多同类信息时,新增字段是代价最低的做法。例如原来只有 contact_phone,现在需要同时记录手机和座机,可以保留 contact_phone,新增 contact_phone_alt,而不是把两个号码塞进一个字段用分隔符拼接。
这种做法成立的条件有三个:旧字段的历史值仍然可读;读取方可以接受“新字段为空”的过渡状态;写入逻辑能明确区分“没填”和“填了空字符串”。如果旧字段已经承担了多种含义,新增字段只会让含义继续分裂,这时应转向改写。
一个实际动作是:先对旧字段做一次取值分布检查,看它实际存了多少种格式。如果格式超过两种且无法用同一规则解析,就说明保留策略只能短期使用,下一步应准备迁移方案。
当旧字段的语义已经偏离最初设计,例如原本用于存“订单备注”,后来被用来存“订单状态码”,继续保留会让每个读取方都要记住这段历史。此时应把旧字段冻结为只读,新增一个语义正确的新字段,再分批回填历史数据。
改写的前提是你能列出所有写入方和读取方。漏掉一个定时任务或后台脚本,就可能在迁移后继续往旧字段写数据,造成两套值并存。可以先在写入入口加一层兼容逻辑:新写入一律进新字段,旧字段只保留历史值,观察一段时间后再决定是否下线旧字段。
代价也很明确:迁移期间查询要同时考虑新旧字段,报表口径可能短暂不一致。如果业务对历史统计的连续性要求很高,改写就要安排在对账周期之外,并保留回滚用的旧字段副本。
当扩展字段数量多、变动频繁,或者同一实体需要保存多组同类记录时,继续在主表加列会让表结构越来越难维护。这时可以退出“一张主表加很多列”的思路,另建一张扩展表,用实体标识关联,每个扩展项存一行。
这种结构适合字段会持续增加、且不同记录需要的扩展项并不相同的场景。代价是查询变复杂,原本一次简单查询能取到的值,现在需要关联或二次查询;如果读取端很多,还要统一封装访问方式,否则每个页面各写一套关联逻辑,后续更难改。
判断是否值得退出,可以看一个假设例子:某论坛用户表已有十二个扩展列,其中一半列在九成记录里为空。若继续加列,空列会继续增多;若改成扩展表,空值不再占列,但每次读取用户完整资料要多一次关联。哪种更合适,取决于读取频率和字段增长速度,而不是单纯看列数。
不管选保留、改写还是退出,都不要一次性改全量数据。可以先选一小批记录,按新方案写入,再用同一套读取逻辑取出来比对。重点看三件事:旧值是否还能被正确解释;新值是否在缺失时表现为“未知”而不是“空”;读取方是否需要在代码里写额外分支。
如果试写后发现读取方大量依赖旧字段的模糊含义,说明改写条件还不成熟,应先补文档和访问封装,再推进迁移。如果试写顺利,下一步才是分批回填历史数据,并保留旧字段一段时间作为对照。
回到最初的问题:上线后发现字段不够用,优先看旧字段是否仍可解释。可解释就保留并新增,语义错位就冻结旧字段并改写,字段持续膨胀且读取方可控时才退出旧结构另建扩展表。先做小范围试写,再根据读取方是否需要额外分支决定下一步,而不是一次性全量迁移。