三大范式与反范式
约 975 字大约 3 分钟
布欧-Lewyon
2026-05-15
首页 › MySQL › 表设计(在新窗口打开) › 三大范式与反范式
数据库范式(Normalization)是表结构设计的一组准则,用于减少数据冗余和更新异常。实际工程中很少严格遵循 BCNF(Boyce-Codd Normal Form,巴斯-科德范式),第三范式是多数业务系统的实用选择。
第一范式(1NF)
要求:每个字段都是不可再分的原子值。
-- 违反 1NF:hobbies 字段存了多个值
CREATE TABLE user_bad (
id INT PRIMARY KEY,
name VARCHAR(50),
hobbies VARCHAR(100) -- "篮球,游泳,阅读"
);
-- 符合 1NF:每个爱好独立一行
CREATE TABLE user_hobby (
user_id INT,
hobby VARCHAR(20),
PRIMARY KEY (user_id, hobby)
);现代数据库开发中,JSON 类型提供了一定程度的"非原子"能力,但 JSON 列的字段仍应遵循业务层的原子语义。
第二范式(2NF)
前提:满足 1NF。
要求:消除对复合主键中部分主键的依赖(即非主键列必须完全依赖于整个主键)。
-- 违反 2NF:复合主键 (student_id, course_id),但 teacher 只依赖 course_id
CREATE TABLE enrollment_bad (
student_id INT,
course_id INT,
score INT,
teacher VARCHAR(50), -- 只依赖 course_id,不是完全依赖整个主键
PRIMARY KEY (student_id, course_id)
);
-- 符合 2NF:拆成两张表
CREATE TABLE enrollment (
student_id INT,
course_id INT,
score INT,
PRIMARY KEY (student_id, course_id)
);
CREATE TABLE course (
id INT PRIMARY KEY,
name VARCHAR(50),
teacher VARCHAR(50)
);如果表是单列主键,那它天然满足 2NF(因为不存在"部分依赖")。
第三范式(3NF)
前提:满足 2NF。
要求:消除传递依赖——非主键列不能依赖于另一个非主键列。
-- 违反 3NF:dept_name 传递依赖于 dept_id(dept_id → dept_name)
CREATE TABLE employee_bad (
id INT PRIMARY KEY,
name VARCHAR(50),
dept_id INT,
dept_name VARCHAR(50), -- 传递依赖:id → dept_id → dept_name
dept_addr VARCHAR(100) -- 另一个传递依赖
);
-- 符合 3NF:部门信息独立成表
CREATE TABLE employee (
id INT PRIMARY KEY,
name VARCHAR(50),
dept_id INT
);
CREATE TABLE department (
id INT PRIMARY KEY,
name VARCHAR(50),
addr VARCHAR(100)
);反范式(Denormalization)
有时为了查询性能,会刻意引入冗余,这就是反范式。
-- 反范式设计:把部门名冗余到员工表,省去 JOIN
CREATE TABLE employee_denormalized (
id INT PRIMARY KEY,
name VARCHAR(50),
dept_id INT,
dept_name VARCHAR(50), -- 冗余字段
dept_addr VARCHAR(100) -- 冗余字段
);何时反范式
| 场景 | 说明 |
|---|---|
| 高频查询 + 低频更新 | 部门名不常改,但员工查询频繁,冗余可省 JOIN |
| 大数据量报表 | 宽表避免多层 JOIN 拖慢查询 |
| 分库分表 | 跨库无法 JOIN,冗余字段保证查询完整性 |
反范式的代价
- 更新成本:修改部门名需更新所有员工行(更新异常)。
- 数据一致性:应用层需要保证冗余数据同步——可用触发器或最终一致性方案。
- 存储放大:冗余字段占用额外空间。
实际项目中的取舍
典型原则:
- 默认设计到 3NF。
- 在读远超写的报表、聚合查询中,适度反范式。
- 在写入频繁的表中,保持范式化以避免更新异常。
- 反范式不等于无设计——冗余字段应有明确的更新策略(同步/异步/定时)。
小结
- 1NF:字段原子化;2NF:消除部分依赖(针对复合主键);3NF:消除传递依赖。
- 第三范式是大多数业务系统的基线,减少数据冗余和更新异常。
- 反范式通过引入冗余换取查询性能,适用于读多写少、报表查询等场景。
- 范式化与反范式不是非此即彼——同一系统的不同表可采取不同策略。
上一节:公用表表达式(CTE) 下一节:表关系与 E-R 图
