规范化
在关系数据库中,关系模式的设计需要满足一定要求,称这些要求为范式。
范式的层次由低到高分为六种:1NF、2NF、3NF、BCNF、4NF、5NF。
范式的层次越高,要求越严格。
数据依赖
介绍范式之前,得先了解数据依赖。
数据依赖分为两种:函数依赖和多值依赖。
1. 函数依赖
以关系模式 R(A, B, C, D, E) 为例:
属性间的关系如下:
(A, B) -> E
A -> C
C -> D
其中 X -> Y
表示 X 的取值 x 唯一标识 Y 的取值 y。
主键为 (A, B)
,主键里的属性称为主属性,其他属性称非主属性。
E 由所有主属性共同决定,称 E 完全依赖于主键,是多对一的关系。
C 仅由主键中的属性 A 决定,称 C 部分依赖于主键,是一对一的关系。
D 通过 C 由属性 A 决定,称 D 传递依赖于 A。
2. 多值依赖
以关系模式 R(X, Y, Z) 为例:
其中 (X, Y) ->-> Z
表示 (X, Y) 的取值 (x, y) 对应 Z 的多个值 {z1, z2, …}。
若 Z 的取值仅和 X 有关,则称 (X, Y) ->-> Z
为多值依赖
。
若 Y 为空集,则称 X ->-> Z
为平凡的多值依赖,是多对多的关系。
若 Y 不为空集,则称 (X, Y) ->-> Z
为非平凡的多值依赖,是一对多的关系。
1NF
1NF 要求属性不能再继续分解,且重复元组。
有时因为业务需求和优化查询效率,可以不遵循 1NF。
2NF
在 1NF 基础上,2NF 要求非主属性完全函数依赖于主键。
以 R(学生 ID, 课程 ID, 成绩, 系名) 为例:
在关系模式 R 中,(学生 ID, 课程 ID) 是主键。
系名仅由学生 ID 决定,即系名部分函数依赖于主键。
关系模式 R 会产生以下几个问题:
(1)插入异常:插入 (学生 ID, 系名) 时,由于主键不全,导致插入失败。
(2)删除异常:若学生只选了一门课,删除该课程会导致信息丢失(系名和学生 ID)。
(3)数据冗余:如果学生转系,需要修改多个元组。
解决方法是将 R 分解成 S(学生 ID, 系名) 和 C(学生 ID, 课程 ID, 成绩)。
可通过自然连接合并 S 和 C 获得 R。
3NF
在 2NF 基础上,非主属性不函数依赖于其他非主属性。
举一个不满足 3NF 的例子:R(学生 ID, 系名, 学生住处)。
在 R 中,学生 ID 是主键。
学生住处函数依赖于非主属性系名,因此关系模式 R 不满足 3NF。
若一个关系不满足 3NF,就会产生 2NF 相类似的问题。
解决方法是将 R 分解为 S(学生 ID,系名) 和 D(系名,学生住处)。
BCNF
BCNF 也称为扩充的 3NF。
在 3NF 基础上,BCNF 消除了主属性对其他属性的依赖。
举一个不满足 BCNF 的例子:R(学生 ID,教师 ID,课程 ID)。
在 R 中,每个教师只教一门课,每门课有若干教师,某一学生选定某门课,就对应一个固定的教师。
由语义可得如下的函数依赖项:
(学生 ID, 课程 ID) --> 教师 ID
(学生 ID, 教师 ID) --> 课程 ID
教师 ID --> 课程 ID
其中 (学生 ID, 课程 ID) 和 (学生 ID, 教师 ID) 均可作为主键。
若以 (学生 ID, 课程 ID) 作为主键,则主属性课程 ID 依赖于非主属性教师 ID,不满足 BCNF。
若以 (学生 ID, 教师 ID) 作为主键,则非主属性课程 ID 部分依赖于主键,不满足 2NF,也就不满足 BCNF。
解决方法是将 R 分解为 S(学生 ID, 教师 ID) 和 T(教师 ID,课程 ID)。
BCNF 在函数依赖范畴内实现了彻底的分离,已消除了插入和删除的异常。
4NF
在 BCNF 基础上,消除非平凡多值依赖。
以存在非平凡多值依赖的关系模式 R(X, Y, Z) 为例,其非平凡多值依赖为 (X, Y) ->-> Z
。
R 的操作会有如下问题:
(1)插入繁琐:若要增加 Y 的值 y1,需插入多个元组。
(2)删除繁琐:若要删除 Y 的值 y1,需删除多个元组。
(3)更新繁琐:若要更新 Y 的值 y1,需更新多个元组。
(4)数据冗余:对于 Z 不同的取值,(X,Y) 要存储多个元组。
解决方法是将 R 拆解为 S(X, Y) 和 T(X, Z)。
本质是将多对多的关系转化为一对多的关系。
规划化
规范化(normalization)是一个过程,逐步消除数据依赖中不合适的部分。
规范化是通过对关系模式的分解来实现的,即把低一级的关系模式分解为若干个高一级的关系模式。
- 1NF:消除非主属性对主键的部分函数依赖
- 2NF:消除非主属性对主键的传递函数依赖
- 3NF:消除主属性对主键的部分和传递函数依赖
- 4NF:消除非平凡的多值依赖
4NF 已经解决函数依赖和多值依赖的问题,5NF 处理连接依赖,这里不再讨论。
需要注意的是,过度规范化的设计可能会导致查询的复杂性增加,从而影响查询性能。
有时候为了业务需求和优化查询效率,关系模式甚至不符合 1NF。