📄 一句话概括
规范化=拆表+整理,让一条事实只存一处——重复没了,改漏也就没了。
📝 本节和前面几节的关系
设计表时最容易犯错的地方就是【什么都塞进一张表】。本节讲怎么拆、为什么要拆。
一、反面教材:一张大表包打天下
把订单号、客户、商品名、数量全塞进一张表——同一个商品名在每条记录里重复抄写。 麻烦随即而来:改一次商品名要改很多行,漏改一处,同一个商品就有了两个名字; 存储也浪费:重复的字符串占着多份空间——数据越大,浪费越大。
二、拆表:一条事实只存一处
拆:商品只留一张商品表(商品号、商品名),商品名只出现一次; 指:订单表改存商品号,指向商品表——要用名字时顺着编号去取; 整:确认每个字段都【直接依赖】它所在表的主键,不为别的表的信息背锅。 拆完再看:改商品名只需动一处,想漏也漏不了。
三、规范化的账
收益:消除重复存储、消除改漏风险、表各管一事便于理解; 代价:查一次要拼多张表(8.5 的 JOIN 就是干这个的),设计时也要多费脑子; 结论:先把【不重复】做对,性能问题用索引等手段另算——顺序不能颠倒。
四、动手 Demo:拆表消除重复
一张重复抄写商品名的订单表,拆成商品表+订单表,数一数省下多少重复。
orders = [("1001", "铅笔", 2), ("1001", "橡皮", 1),
("1002", "铅笔", 5), ("1003", "铅笔", 3)]
names = [o[1] for o in orders]
print("商品名出现", len(names), "次")
print("不同商品只有", len(set(names)), "种")
# 拆表: 商品表只存编号->名字, 订单表存编号
goods = {1: "铅笔", 2: "橡皮"}
print("拆表后商品名只存", len(goods), "次")
实跑输出:
--------------------------------------------------------------------
规范化——通过拆表和整理数据消除浪费
--------------------------------------------------------------------
反面教材: 一张【订单】大表把商品名抄在每条记录里——
同一个商品名重复出现, 改一次要改很多行, 还容易改漏。
规范化前的订单表(部分):
订单1001 波仔 买了 铅笔 x2
订单1001 波仔 买了 橡皮 x1
订单1002 小墨 买了 铅笔 x5
订单1002 小墨 买了 直尺 x2
订单1003 阿池 买了 铅笔 x3
商品名共出现 5 次, 不同商品其实只有 3 种:
橡皮、直尺、铅笔
规范化的做法: 拆成两张表——商品表(商品号, 商品名) 只存一次;
订单表改存(订单号, 客户, 商品号, 数量), 用商品号指过去。
方案 商品名出现次数 改一次商品名要动几处
---------------------------------------------------
拆表前 5 次 5 处
拆表后 3 次 1 处
规范化的目标: 一条事实只存一处——重复没了, 改漏也就没了。
5 条记录里【铅笔】抄了 3 遍——记录一多,重复就是成倍的内存与改漏风险。 规范化的判断标准可以记成一句话:每个字段只描述它所在表的【主角】。
30 秒实验
- 找一张你见过的 Excel 宽表,指出哪几列在重复、可以拆出去。
- 用【一条事实只存一处】的标准,检查自己项目里的一张表。
常见误区
- 以为表越少越简单——一张大表重复满天飞,改一次漏三处才是真麻烦。
- 以为拆得越细越好——拆过头查一次要拼七八张表,该合的时候也要合。
自测三问(点开对答案)
1. 规范化的目标一句话? —— 一条事实只存一处,消除重复与改漏。 2. 拆表之后订单表怎么指向商品? —— 存商品号(编号),用编号去商品表取名字。 3. 规范化的代价是什么? —— 查询要拼多张表,设计时更费脑。- ☐ 下一节(8.5 用主键和外键在表间建立关系)
相关笔记
- LX_CH6_64 — 数据讲究摆法,表结构也是摆法
- 🗄️ 数据库基础 · 索引 — 范式理论在那边成体系
- 💻 计算机是怎样跑起来的 · 索引