设计数据库的六大范式
最近新项目启动,后端需要重新设计数据库。老师傅将这个任务交给了新人,并提醒新人要注意设计数据库的三大范式。
第一个听到这个概念,于是就顺便学习一下。
一、什么是范式
范式说白了就是数据库表格的一些设计规范。
二、为什么需要范式
遵循范式设计规范的数据库,可以有效避免数据冗余,减少数据库空间,减轻维护数据库完整性的麻烦。
三、范式的问题
过于深入地去遵守范式反而会让操作变得困难,需要联系多个表才能得到想要所需要的数据。
为了拿到想要的数据,需要反复查询表格,对硬盘I/O速度有较高的要求,这在高并发性的情景下非常不好使。
因此范式等级越高,其性能就越差。
一般项目中,第三范式已经够用了。因此本文只总结前三个范式,后面的暂时不管。
四、有哪些范式
目前比较常说的范式一共有六个,即1NF、2NF、3NF、BC范式(巴斯科德范式)、4NF、5NF。
这些范式是层层递进的,也就是说要实现后一个范式的规范,是需要遵循之前所有范式的规范。
在了解范式之前,需要明确几个概念:
- 函数依赖:如果一个表中的字段Y是由另外一个字段X或一组字段X的值来决定的, 那么就可以说Y函数依赖于X。
- 候选键:我的理解是可以用来作为查询表格的最小字段组合就是一个候选键。比如一张学生表(学号、姓名、性别、身份证号、教师编号),其中学号、身份证号就是这个表的候选键
- 主键:又称主关键字或主码,我们一般可以将候选键中的某一个人为设置为主键,比如学生表,我可设置学号为主键,也可以设置身份证号为主键。
1. 第一范式(1NF)
当表格中的所有属性都具有原子性,无法再被分割,那么我们就可以说这个表格遵循了第一范式
比如,下面这个学生信息表格:
学生编号 | 姓名 | 性别 | 联系方式 |
---|---|---|---|
20080901 | 张三 | 男 | email:zs@126.com,phone:88886666 |
20080902 | 李四 | 女 | email:ls@126.com,phone:66668888 |
联系方式里面既可以保存邮箱,又可以保存电话号码,那么我们就可以将它拆开,以此来遵循第一范式:
学生编号 | 姓名 | 性别 | 邮箱 | 电话号码 |
---|---|---|---|---|
20080901 | 张三 | 男 | email:zs@126.com | phone:88886666 |
20080902 | 李四 | 女 | email:ls@126.com | phone:66668888 |
2. 第二范式(2NF)
表格中的所有非主属性都完全函数依赖于候选键,而不是部分依赖,那这个表格就符合第二规范。
比如下面这一张学生选课表:
学生 | 课程 | 教师 | 教师职称 | 教材 | 教室 | 上课时间 |
---|---|---|---|---|---|---|
李四 | Spring | 张老师 | java讲师 | 《Spring深入浅出》 | 301 | 08:00 |
张三 | Struts | 杨老师 | java讲师 | 《Struts | in | Action》 |
这里可以通过(学生,课程)来确定(教师,教师职称,教材,教师,上课时间),所以我们可以把(学生,课程)作为主键。
但是其中教材不完全依赖于(学生,课程),其实只要知道课程,我们就可以确定教材了。
这就是不完全依赖,也就是部分依赖,当出现这种情况时,就不符合2NF了。
因此我们可以将课程和教材拿出来单独做一张表,像这样:
学生选课表
学生 课程 教师 教师职称 教室 上课时间 李四 Spring 张老师 java讲师 301 08:00 张三 Struts 杨老师 java讲师 302 13:30 课程表
课程 教材 Spring 《Spring深入浅出》 Struts 《Struts
也就是将原来学生选课表的教材列抽离出来,单独与课程做成课程表,这样出来的表格消除了部分依赖,符合2NF规范。
2NF可以减少插入异常、删除异常以及修改异常
3. 第三范式(3NF)
当非主属性之间存在函数依赖,也就是传递依赖,那么这个表就不符合3NF。
比如上面的学生选课表,教师依赖于(学生,课程),而教师职称又依赖于(教师),这样就形成了传递依赖。
于是需要经过以下修改:
选课表
学生 课程 教师 教室 上课时间 李四 Spring 张老师 301 08:00 张三 Struts 杨老师 302 13:30 教师表
教师 教师职称 张老师 java讲师 杨老师 java讲师
这样教师跟职称就有地方存了,不会因为没有学生选他们的课,导致他们完全消失不见了。
另外当教师的职称发生变化时,也不需要一个个去修改了。
总的来说,以上三个范式对数据库表格的设计要求就是原子性、完全依赖以及没有传递依赖。
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!