设计关系数据库时,遵从不同的规范要求,设计出合理的关系型数据库,这些不同的规范要求被称为不同的范
式,各种范式呈递次规范,越高的范式数据库冗余越小。
目前关系数据库有
5+1
级范式:第一范式
(1NF)
、第二范式
(2NF)
、第三范式
(3NF)
、巴斯
-
科德范式
(BCNF)
、
第四范式
(4NF)
和第五范式
(5NF
,又称完美范式
)
。满足最低要求的范式是第一范式
(1NF)
。在第一范式的基础
上进一步满足更多规范要求的称为第二范式
(2NF)
,其余范式以次类推。如果不满足所要求的范式,则将不满
足范式要求的部分进行分表。一般说来,数据库只需满足第三范式
(3NF)
就行了【反范式】。
注意:范式等级越高,数据冗余越小,但是表的数量就越多,查询效率则越低,所以有时候为了提高查询效率,
可以降低范式要求
----
反范式
设计的起点和依据是需求说明文档
主键的定义
主键可分为
2
大类:自然主键和代理主键。一般建议使用代理主键
1
、将表中的所有列的组合当作主键
--
候选码
2
、去除其中某些列查看是否还能唯一标识一行数据
3
、最后找到的所有候选码的真子集就是主码
最佳实践:可以在表中添加一个与业务无关的字段充当主键
id bigint primary key auto_increment
NF1
所有列不可分,字段满足原子性
定义学生,学生
(
编号、班级编号、姓名、亲属
)
,这个亲属列是可分的,所以将亲属列划分到另外表中,从而
使剩余的列满足
NF1
,最终结构选择为 学生
(
编号、班级编号、姓名
)
、学生亲属
(
姓名、关系、外码
)
NF2
消除对主键的部分依赖
定义学生,学生
(
编号、班级编号、姓名、宿舍楼号
)
,主键为复合主键
(
编号、班级编号
)
,这里会发现一旦班
级编号确定则所属的系别就确定,系别确定则宿舍楼号确定。宿舍楼号部分依赖主键,不是依赖整个主键。解
决问题的方法为分表 学生
(
编号、班级编号、姓名
)
学生住宿
(
班级编号、宿舍楼号
)
NF3
消除对主键的传递依赖
定义学生,学生(学号
pk
、系别、宿舍楼号),主键为学号,所以自然满足
NF2
,但是一旦系别确定则宿舍
楼号确定,所以宿舍楼号依赖于系别,不是依赖于学号。这里就是传递依赖:宿舍楼号
-->
系别
-->
学号
pk
。
解决问题的方法为分表
范式和反范式
应用范式可以减少数据冗余,但是范式级别越高,则创建表的数量越多,查询效率则越低。所以在具体开发中
经常采用降低范式要求,采用合理冗余数据的方式以提高查询效率
考虑查询效率,所以一般只达到
NF3
即可,甚至有时会了提高查询效率会有意降低范式要求【反范式】
表和表之间关系
表和表【实体】之间的关系有
3
种:
1
、一对一
1:1
,例如一个人只能有一个身份证,一个身份证只能属于一个人
2
、一对多或者多对一
1:m
或者
m:1
,例如一个类目可以包含多个商品,一个商品只能属于一个类目
3
、多对多
n:m
,例如一个学生可以选修多门课程,一个课程可以被多个学生选修
考察表【实体】之间关系的方法:中立