结论先给:上线后发现字段不够用,扩展路径取决于一件事——现有数据能否接受一次有损或无损的结构变更。如果旧字段的数据可以重新映射,优先做兼容式扩展,让新旧结构并存一段时间;如果旧数据必须原样保留且无法映射,就要走迁移式扩展,用新表或新集合承接,旧结构逐步只读。判断依据不是字段数量,而是“旧值能否自动填进新结构”。
字段不够用通常表现为三种情况:需要给已有记录补一个新属性、需要把原来一个字段拆成多个、需要让一条记录对应多条子项。前两种多数可以用兼容式扩展解决,第三种往往意味着关系变了,必须迁移。
一个可执行的判断动作:从数据库或内容模型里导出最近一批真实记录,挑出字段值最复杂的若干条,手工尝试把它们填进你设想的新结构。如果超过一小部分记录无法自动对应,说明这不是加字段,而是改模型。
这里有个容易被忽略的例外:如果新字段只是用于统计或展示,且允许为空,那么即使旧记录没有值,也不构成扩展障碍。反之,如果新字段参与权限判断、计费或对外接口返回,空值会变成业务错误,必须先补默认规则。
适用条件是旧字段值能通过明确规则转成新字段,例如把“姓名”拆成“姓”和“名”,或把自由文本标签规范成枚举。此时不必停机,可以分步走。
这个动作的结果直接影响下一步:如果回填失败率很低且原因集中,说明映射规则基本成立,可以继续推进切换;如果失败原因分散,说明你还没真正理解旧数据的分布,此时应暂停切换,先扩大样本再定规则。
需要说明的是,回填脚本跑完不代表数据正确。回填成功数、接口报错数归零,也可能是任务根本没覆盖到全部记录,或者读取逻辑仍在读旧字段。要验证扩展是否生效,应直接查询新字段的填充率和抽样比对,而不是只看任务日志。
适用条件是旧结构本身已经表达不了新关系,比如原来一条订单只有一个收货地址,现在要支持多个地址并区分默认地址。这时继续在旧表加字段只会让查询越来越难维护。
做法是新建承载新结构的表或集合,把旧数据按规则导入,旧结构保留只读一段时间作为回退依据。导入时给每条新记录保留对旧记录的引用,便于出现问题时定位。
实施中最容易出错的是默认值。新结构里的“是否默认地址”这类字段,在旧数据里没有对应信息,必须明确一条业务规则,例如把最早的一条设为默认,而不是留给程序随机决定。
例外情况:如果这个站点仍处于上线初期,真实数据量很小,且没有对外承诺的数据接口,那么直接重建结构、丢弃测试期数据的成本可能低于迁移成本。这个判断的前提是你确认那些数据没有保留价值,而不是嫌迁移麻烦。
很多时候你没有数据库直连权限,也拿不到全量数据。这不等于无法推进,但能得出的结论有限。
如果连导出权限也没有,退一步的做法是把扩展需求写成明确的字段定义和取值规则,交给有权限的人执行,同时约定验证方式,例如回填后抽查多少条、由谁确认。这比在没有依据的情况下直接改结构更可靠。
无论走哪条路径,扩展完成后应留下三样东西:新字段的定义和取值范围、旧字段的处置状态(继续写入、只读还是废弃)、以及一次可重复的验证方法。缺少第三样,下一次字段不够用时,你仍然只能靠猜。
验证方法可以很简单,例如固定一段查询,统计新字段的填充率和异常值数量,每次结构调整后跑一遍对比。它的作用不是证明系统没问题,而是让变化可见。
字段扩展本身不会因为用了某个框架或内容管理系统就自动变简单,关键始终是旧数据能否映射、新规则是否明确、以及验证是否可重复。把这三件事定下来,再决定是兼容式扩展还是迁移式扩展,返工的概率会低很多。