答案取决于“不够用”的性质:是字段数量少,还是字段之间的关系没被建模。前者可以增量加列,后者如果继续加列,会让查询、后台表单和模板逻辑一起变复杂。判断方法很直接:打开最近三条需要特殊处理的记录,看它们的差异是“多了几个值”,还是“同一种内容在不同记录里含义不同”。前者适合加字段,后者适合把内容拆成独立实体。
第一种解释是字段少。假设你的文章表只有标题、正文、发布时间、作者,上线后想给部分文章加“系列名”“阅读时长”“封面图”,这些都属于同一篇文章的附加属性,加列即可。第二种解释是模型错位。假设你想记录一篇文章的多个作者、多个来源链接、多个版本修订,这些不是文章的属性,而是与文章有一对多关系的独立对象。如果硬塞进一个文本字段,比如把作者写成“张三,李四”,短期能显示,长期无法按作者筛选、无法统计每人文章数,也无法在作者改名时统一更新。
能区分这两种解释的证据有三类。第一,看是否需要单独查询:如果某个值将来要用来筛选、排序或聚合,它就不该被塞进长文本。第二,看是否重复出现:如果同一组值在大量记录中重复,说明它值得独立成表或独立字段。第三,看修改频率:如果某个值会独立变化,比如作者简介、系列说明,独立存储能避免批量替换正文。
不要直接改数据库。先导出最近二十条记录,逐一标注每个字段的用途:展示、筛选、排序、统计、关联。只有“展示”用途的字段,扩展成本最低;“筛选和统计”用途的字段,需要索引或独立表;“关联”用途的字段,需要外键或中间表。这个盘点动作的结果会直接影响下一步:如果多数新需求落在展示,加列即可;如果落在筛选和关联,就要先设计实体关系,再迁移数据。
假设一个短例子:你原本用一列 tags 存“SEO,建站,博客”,后来想按标签出聚合页。继续用逗号分隔,查询会变成模糊匹配,既慢又容易误匹配。把标签拆成 tags 表和 post_tags 中间表后,聚合页可以按标签主键查询。这个例子的数字只是说明比较方法,不代表真实数据量或性能结论。
加列适合可空、低频、不需要单独查询的属性,代价是表变宽,后台表单要同步增加输入项。加表适合一对多、多对多和需要独立生命周期的对象,代价是查询需要关联,写入需要事务或补偿逻辑。如果使用文档型存储,给文档增加字段看似最灵活,但代价是历史文档缺省值不统一,聚合和校验要额外处理。三种方式没有绝对优劣,关键看你的查询方式和后台编辑流程是否跟得上。
一个实际动作是:先在一个只读副本或本地环境加字段,跑一遍列表页、详情页、后台编辑页和导出功能。如果导出功能报错或后台保存后详情页不显示,说明扩展点不止数据库,还涉及模板、接口和导出逻辑。这个结果会决定你是继续增量修改,还是先冻结新字段、集中做一次数据模型调整。
个别样本成立不代表可以照搬。比如你只有三篇文章时,把“来源”写进正文末尾完全够用;文章到三百篇、来源需要去重和统计时,正文里的来源就无法可靠提取。边界条件是:当同一类信息需要跨记录比较,或需要在不改正文的情况下更新,就必须从正文中拆出。反过来,如果某个字段只在一两篇特殊文章里出现,且永远不参与筛选,保留为正文的一部分或一个备注字段,比新建实体更省事。
另一个边界是多人协作。单人维护时,字段命名随意一点还能靠记忆;多人编辑时,同一个“作者”字段可能被填成姓名、昵称或邮箱,后续统计就会分裂。此时应先固定字段含义和取值来源,再决定是否拆表。这个动作的结果是:如果字段含义无法统一,加再多列也只是把混乱分散到更多地方。
这套顺序的重点不是一次设计完美,而是让每次扩展都能回退。上线后才发现字段不够用并不可怕,可怕的是把关联关系继续塞进文本字段,导致后面每次查询都要靠模糊匹配。先判断“不够用”属于哪一类,再选择加列、加表或调整文档结构,扩展才会停留在可维护的范围内。