先给结论:不要急着改表结构。先判断缺的是“存储字段”还是“派生字段”。如果原始数据已经落库,只是页面和查询需要更多维度,优先加派生表或视图;如果原始数据从一开始就没采集,才需要动采集层和表结构。判断依据是:这个字段能不能从已有数据算出来。
很多团队上线后喊“字段不够”,实际是两种情况混在一起。第一种是采集时就没写入,比如表单只存了手机号,没存来源页面和首次落地页,事后无法还原。第二种是数据其实在,只是散落在日志、订单备注或第三方回调里,没有整理成可查询的字段。
区分方法很直接:拿一条真实记录,问“这个值当时能不能被观察到”。能被观察到但没单独存,属于派生问题;当时根本没有这个观察点,属于采集问题。这个判断决定了后面是加视图还是改写入逻辑,方向错了会白做一轮迁移。
如果原始字段足够推导,最省事的做法是新建一张派生表或物化视图,用定时任务或写入触发器把计算结果补上。这样主表不动,历史数据可以批量回填,线上写入路径也不受影响。
具体动作可以这样安排:
这个动作的结果会直接影响下一步:如果回填后抽样核对发现大量空值,说明推导依赖的原始字段本身就有缺失,那就不是派生层能解决的,要回到采集层排查。反过来,如果回填顺利,就可以把派生层作为长期方案,不必再动主表。
假设一个场景:表单提交时存了created_at和user_id,但没有单独的“首次来源”字段。如果日志里保留了带来源参数的首次访问记录,就可以按user_id关联算出首次来源,写进派生表。这只是说明推导思路的假设例子,不代表任何具体系统的默认行为。
如果当时压根没记录,比如没有埋点、没有存请求头里的来源信息,那么任何事后推导都不可靠。这时只能改采集层:在写入逻辑里加字段,让新数据从某个时间点开始带上这个值。
关键取舍是:历史数据补不回来,只能接受一段空白期,或者用间接信号做粗略近似。近似值要明确标注为估算,不能和真实采集值混在同一列里比较。常见做法是新增字段先允许为空,等新数据积累一段时间后再决定是否设默认值或做约束。
实施顺序建议是:先改写入代码并加监控,确认新字段有值率稳定;再考虑是否对旧数据做近似填充;最后才调整查询和报表口径。如果跳过监控直接改报表,很容易把“新字段为空”误读成“业务量下降”。
第一个坑是把字段扩展当成纯技术任务,不通知使用数据的人。字段含义变了、空值变多、口径从“全量”变成“仅新数据”,这些都会影响下游判断。上线前应同步说明新字段的生效时间点和适用范围。
第二个坑是一次性加太多字段。每加一个字段都增加写入成本和维护负担,而且很多字段加了之后没人用。更稳的做法是按实际查询需求分批加,每批加完后观察一段时间再决定下一批。
还有一个例外:如果数据量很小、写入压力不大,直接改主表加字段也可以接受,不必强上派生层。派生层的价值主要体现在数据量大、写入路径敏感或需要保留历史快照的场景。条件不同,选择就不同。
验证不看“字段加没加上”,而看原来卡住的那个查询或页面是否恢复正常。可以拿上线前失败的具体操作复现一遍,确认返回结果完整、数值合理。同时抽查一批新旧数据,确认新字段在旧记录上为空、在新记录上有值,符合预期。
如果复现仍然失败,要区分是字段本身不对,还是查询逻辑没跟着改。前者回到采集或派生层排查,后者只是查询没切换。这个区分能避免把查询问题误判成数据问题,从而少做一轮无效迁移。