先给结论:不要直接在原表上改字段名或删字段,而应先判断“缺口属于哪一类”,再选择加列、加附表还是拆出独立实体。判断依据不是字段数量,而是新旧数据能否共存、历史记录是否要保留、以及业务方能否接受一段时间的双写。下面用一个假设情境说明决策过程。
假设某云南茶叶批发企业用自建站承接询价,上线时“询价单”只有姓名、电话、意向品类、留言四个字段。半年后业务要求按“采购频次、目标价位区间、是否需要样品、预计到货城市”做客户分层,还要让同一客户多次询价归到一条客户记录下。原来的单表结构立刻不够用,而且已经积累了一批历史询价。问题不在字段太少,而在于“询价”和“客户”被压在了一张表里。
这时先做一件事:把现有数据导出做一次只读快照,记录总行数、空值比例和重复电话数量。这个动作的结果直接决定下一步——如果重复电话占比很低,说明客户归并需求弱,可以只在原表加列;如果重复明显,就要考虑拆表,否则后面每次查询都要在应用层去重。
字段不够用通常不是同一种病,处理方式差别很大。
区分方法很直接:问一句“这条新信息,对同一条旧记录是零条、一条还是多条”。零条或一条,加列;多条,建表。答不上来,说明业务规则还没谈清,此时改库只会把混乱固化进结构。
如果确认是属性缺口,加列是成本最低的路径。适用条件有三个:新字段对历史数据允许为空;查询仍以单条记录为主;前端表单可以分步补录。操作上给新列设默认空值,不设非空约束,先让写入跑通,再回填历史数据。
如果缺口是“多条”,但数量有限且结构稳定,比如每个询价最多三个联系人,可以建一张联系人附表,用主表 ID 关联。它的代价是每次读取要联表,好处是主表保持干净。判断取舍看读取频率:列表页要展示联系人时,联表开销会累积,这时宁可把常用字段冗余回主表,用写入时的同步逻辑换取读取速度。
当同一客户会反复出现,且分层、跟进、复购都要围绕客户展开时,就必须把客户从询价单里拆出来,形成“客户表 + 询价表”的结构。触发条件可以量化为:重复标识(如电话或统一社会信用代码)在询价记录中反复出现,且业务方明确要求按客户维度统计。此时继续在询价表加列,会导致同一客户的信息在多行里不一致。
拆表不是一次性动作。稳妥的顺序是:先建新表并双写,让新数据同时进旧表和新表;再用脚本把历史数据归并进新表,人工核对疑似重复项;最后切换读取来源,旧字段保留一段时间只读。每一步的验证结果决定下一步——如果双写期间新旧记录数对不上,就不要进入切换阶段。
如果上线后发现某些统计突然归零,不要立刻断定是扩展改坏了。也可能是查询条件变了、时间范围默认值改了、或者新字段尚未回填导致过滤掉全部记录。先比对快照行数,再定位是数据问题还是查询问题。
面向云南本地客户的站点,询价往往集中在茶叶、农产品、旅游服务等品类,客户复购和转介绍比例不低,因此“客户”这个实体通常值得早点独立出来。但也不必一开始就设计成复杂的关系模型:先用加列撑过验证期,等重复客户和多次询价的证据出现,再拆表,代价更小。扩展字段的时机判断,本质上是在问业务规则是否已经稳定到值得固化进结构。