能否直接扩展,取决于原字段是“存错了”还是“装不下”。如果只是缺几个新字段,可以增量加列并保留旧数据;如果原设计把可变内容压进一个文本字段,或把多值关系塞进单列,就必须先拆表再迁移,否则新字段加得越多,查询和统计越不可靠。下面用一个假设情境说明判断顺序。
假设有一家做企业培训的站点,上线时“报名记录”只设计了姓名、电话、课程名、备注四个字段。运营三个月后要按城市、班期、企业规模筛选学员,还要记录同一人报多门课。此时加“城市”一列能解决第一类需求,但“同一人多课程”加列解决不了,因为一个人对应多条课程记录,属于一对多关系。
区分方法很直接:新需求里的每个值,对同一条主记录是只有一个,还是可能有多个。只有一个,属于缺字段;可能有多个,或需要独立查询、独立统计,属于关系缺失。前者可以增量扩展,后者必须新增关联表。判断错方向,后续每加一个筛选条件都要再改一次表结构。
确认只是缺字段后,扩展动作按这个顺序做:先在数据库增加允许为空的新列,再让写入逻辑同时写新旧结构,然后回填历史记录,最后才把新列设为必填。跳过回填直接设必填,旧数据会写入失败;先改必填再补数据,线上表单会立刻报错。
假设报名记录要新增“所在城市”。第一步加一个可空的 city 列;第二步表单提交时写入该值;第三步对已有记录按电话归属地或人工补录回填;第四步确认没有空值后,再决定是否加非空约束。这个动作的结果决定下一步:如果回填后仍有大量空值,说明旧数据本身缺少判断依据,此时不应强行设必填,而应保留可空并让新流程逐步补齐。
当同一主体对应多条记录时,继续在原表加“课程2”“课程3”这类列,会带来三个后果:列数随业务增长失控;查询“报了某课程的所有人”要遍历多列;统计人数时容易重复计数。正确做法是新增一张关联表,至少包含主记录标识、课程标识和报名时间,原表只保留与本人相关且唯一的信息。
迁移时的实际动作是:先建关联表并双写,再把原表里的课程信息逐条拆进关联表,核对条数一致后,才停止写入旧字段。核对这一步不能省,因为拆分过程中最容易出现一条原记录对应多条课程却只迁移了一条的情况。条数对不上,就不要删除旧字段,保留它作为回查依据。
结构改完不等于问题解决。新增关联表后,原来直接读单表的列表页、导出功能和统计口径都要同步调整。判断是否改完的标准不是页面能打开,而是同一批数据在旧口径和新口径下能否对上。
如果统计结果和改版前差异明显,先排查关联是否产生笛卡尔积,再排查是否有历史数据未回填。不要因为某个数字变了就断定新结构有问题,也可能是旧结构本来就在重复计数。
如果新需求只是偶尔人工查看,且数据量很小,用现有字段加备注、导出后手工整理,成本可能低于改表。反过来,如果新需求已经进入日常流程、需要多人同时操作或要定期出报表,拖延扩展会让后续迁移成本更高,因为要处理的数据和依赖会持续增加。
假设站点每月新增记录不足百条,且筛选只发生在季度复盘时,可以先不改结构,把需求记录清楚;一旦筛选变成每周甚至每天使用,就应尽快拆表。这个边界不是固定数字,而是看使用频率和参与人数是否已经让手工方式成为瓶颈。
扩展数据字段的核心不是加多少列,而是先判断新需求属于补充属性还是新增关系。属性缺失可以增量加列并回填,关系缺失必须拆表并双写迁移。把这一步判断清楚,再决定是否设必填、是否删除旧字段,后续的查询和统计才不会反复返工。