范式听起来很学院派,但本质很朴素:
避免重复、歧义和更新异常。
先看一种糟糕设计:
household_book
------------------------------------------------------------
household_no | district_name | address |
citizen1_name | citizen1_birth |
citizen2_name | citizen2_birth |
citizen3_name | citizen3_birth这张表的问题一眼可见:
- 一户如果有 4 个人怎么办
- 市民栏目重复
- 删除一个人可能把整户信息搞乱
- 改区名要改很多行
- 查询“所有市民”也很难写
所以需要范式思维。
第一范式 1NF:一格一值,不要在一个字段里塞列表或重复组
错误:
citizen_names = '林远,周宁,陈舟'正确:一人一行。
第二范式 2NF:如果主键是组合键,非主属性要依赖整个键,而不是只依赖一部分
这在中间表里最容易出问题。比如:
citizen_programs(citizen_id, program_id, citizen_name)如果 citizen_name 只依赖 citizen_id,就不该放这里。
第三范式 3NF:非主属性不要再依赖另一个非主属性
例如在 citizens 表里反复存:
citizen_id, household_id, district_name而 district_name 其实可以通过 households -> districts 推出来,这就是冗余。
规范拆分后更像这样:
districts -> 区信息
households -> 户信息
citizens -> 人信息
move_logs -> 迁移流水要点不是“逢表必拆”,而是:
先把稳定实体拆清楚,再谨慎引入冗余。
范式解决的是“先别把账做乱”;性能优化解决的是“账正了以后怎么翻更快”。