背景
在开发中,我们经常需要考虑如何设计合适的表结构,而则往往需要考虑数据库的范式。数据库的三范式(3NF)是数据库设计过程中用来减少数据冗余和提高数据一致性的重要规则。它们分别是第一范式(1NF)、第二范式(2NF)和第三范式(3NF)。
范式
第一范式(1NF)
定义:一个表满足第一范式,如果其所有字段的值都是原子的(不可再分),且每列的值都属于同一数据类型。
目的:确保每个字段都是最小的数据单位,避免数据冗余和更新异常。
第二范式(2NF)
定义:一个表满足第二范式,如果它首先满足第一范式,且表中的所有非主键列完全依赖于主键,而不是部分依赖。
目的:消除部分依赖,即非主键字段不能依赖于主键的一部分。
示例:
-
不满足 2NF 的表:
学生ID | 课程 | 教师 --------|---------|------ 1 | 数学 | 张老师 1 | 物理 | 李老师 2 | 化学 | 王老师
在这个表中,
教师
只依赖于课程
,而不依赖于整个主键学生ID
和课程
的组合。 -
满足 2NF 的表:
- 学生表:
学生ID | 姓名 --------|-------- 1 | 张三 2 | 李四
- 课程表:
课程 | 教师 --------|------ 数学 | 张老师 物理 | 李老师 化学 | 王老师
- 学生课程表:
学生ID | 课程 --------|------ 1 | 数学 1 | 物理 2 | 化学
第三范式(3NF)
定义:一个表满足第三范式,如果它首先满足第二范式,且没有非主键属性传递依赖于主键。
目的:消除传递依赖,即非主键字段不能依赖于其他非主键字段。
示例:
-
不满足 3NF 的表:
学生ID | 姓名 | 教师 | 教师办公室 --------|--------|--------|---------- 1 | 张三 | 张老师 | 101 1 | 张三 | 李老师 | 102 2 | 李四 | 王老师 | 103
这里,
教师办公室
依赖于教师
,而教师
又依赖于学生ID
,导致传递依赖。 -
满足 3NF 的表:
- 学生表:
学生ID | 姓名 --------|-------- 1 | 张三 2 | 李四
- 教师表:
教师 | 教师办公室 ------|---------- 张老师 | 101 李老师 | 102 王老师 | 103
- 学生课程表:
学生ID | 课程 --------|------ 1 | 数学 1 | 物理 2 | 化学
总结
- 第一范式:确保数据的原子性。
- 第二范式:消除部分依赖,确保非主键属性完全依赖于主键。
- 第三范式:消除传递依赖,确保非主键属性之间没有依赖关系。
范式的优点和缺点
范式化通常可以带来如下好处:
- 范式化的更新操作通常比反范式要快
- 当数据较好的范式化时,就只有很少或者没有重复数据,所以只需要修改更少的数据
- 范式化的表通常更小,可以更好的放入内存里,所以执行操作会更快
- 很少有多余的数据、意味着在检索数据时较少需要distinct 或者 group bu语句。
范式化设计的缺点是,通常需要关联。稍微复杂一些的查询语句,在符合范式化设计上,通常可能都需要至少一次关联。这不但代价昂贵,也可能使一些索引策略失效。例如,范式化可能将列分布在不同的表中,而这些列如果在同一个表中,本可以属于同一个索引。
反范式的优点和缺点
反范式化可能带来如下好处:
- 反范式由于所有数据都在一张表中,可以避免表关联
- 单独的一张表可以使用更有效的索引策略(示例如下:)
混用范式化和反范式
既然范式化和反范式化各有优劣,那我们又该如何选择呢?
需要注意的是,范式化和反范式化都是理论上的原则,现实业务中,很少会很极端的只使用其中一种,而是结合实际需求,混合使用范式化和反范式化。
最常见的反范式的数据方法是复制冗余或缓存。在不同的表中存储相同的特定列,以便于查询时减少表关联来提升效率。
有时提升性能的最好方法是在同一张表中保存衍生的冗余数据。也是通过空间换时间的思想。
选择范式化或反范式化需要综合考虑应用场景、性能要求、数据一致性和维护复杂性。在实际开发中,可能需要根据具体情况进行调整,以达到最佳效果。