先给结论:字段不够用,通常不是把表加宽,而是把“固定列”改成“主表+扩展表”或“属性表”,同时保留旧字段作为兼容层。下面用一个假设情境把决策过程走一遍,说明什么时候该原地加列、什么时候该拆表、什么时候该退出旧字段。
假设你为一家郴州本地服务商建站,最初需求只有“项目名称、联系人、电话、备注”四个字段。上线三个月后,业务方要求按服务区域、项目类型、跟进阶段、来源渠道分别筛选,还要给每条记录挂多个附件。此时原来的单表结构已经不够用。
先别急着改。要做的是把新增需求分成三类:筛选维度(区域、类型、阶段)、多值关系(一条记录对应多个附件或标签)、展示字段(只用于页面显示,不参与查询)。分类不同,扩展方式不同。
适用条件是新增字段数量少、每个字段只有一个值、查询频率高。比如只加一个“服务区域”下拉框,直接加列最省事。代价是字段会持续膨胀,一旦超过十几个可选筛选维度,表单和后台列表都会变得难维护。
适用条件是字段数量多、但每条记录只用到其中一部分。做法是保留主表的固定字段,另建一张扩展表,用记录ID关联,键值对存储。查询时用连接或子查询取回。它的好处是新增字段不用改表结构,坏处是复杂筛选的SQL会变长,索引设计要更谨慎。
适用条件是维度本身需要被管理,比如“服务区域”有层级、有排序、有启用状态。此时把区域做成独立表,主表只存区域ID。这样筛选、统计、批量修改都更清晰。代价是关联查询增多,需要提前规划好索引。
具体动作是:把当前所有字段和未来三个月可能新增的字段列成一张清单,标注“必填/选填”“单值/多值”“是否用于筛选”。然后按下面规则判断:
这个动作的结果会直接影响下一步:如果清单里多值字段超过两个,就不要再走“原地加列”路线,否则后面每次查询都要做字符串拆分,性能和可维护性都会变差。
很多站点上线后不敢改字段,是因为旧页面、旧表单、旧接口还在读老字段。稳妥做法是分三步:
这里要说明一个判断依据:如果只是后台某个统计数字归零,不能直接证明旧字段已经没人用。归零还可能是因为筛选条件变了、定时任务失败、或者数据被归档到另一张表。要结合调用日志和数据库查询记录一起看。
第一是表单校验。字段拆表后,必填校验不能只放在前端,后端也要按新结构重新校验,否则会出现主表有记录、扩展表没数据的空壳记录。第二是历史数据回填。新增维度字段后,旧记录默认是空值,如果直接用于筛选,会漏掉全部旧数据。需要先决定:旧记录是统一填一个“未分类”,还是按规则批量回填。这个决定要在上线前明确,而不是上线后临时补。
假设你选择批量回填,就要先在一个测试库上跑一遍,确认回填规则不会把原本正确的数据覆盖掉。回填完成后再开启新表单的写入,顺序反了会出现新旧数据混在一起、难以区分的情况。
如果出现下面两种信号,继续在旧结构上打补丁的代价可能高于重建:一是每次新增需求都要改动三张以上关联表;二是同一个业务含义在不同表里有不同字段名,维护者需要靠文档才能对应。此时更合理的做法是保留仍然有价值的部分——比如已积累的内容、已配置的维度数据——把数据模型重新设计后再迁移,而不是在旧表上继续加列。
回到开头的假设情境:如果只是加区域和阶段两个筛选字段,原地加列就够;如果要加多附件、多标签、多来源,就应该走主表加扩展表或独立维度表,并给旧字段留出退出期。先做字段清单,再决定改哪张表,是成本最低的起点。