携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第28天,点击查看活动详情
一、第三范式(3rd NF)
举例1:
部门信息表 :每个部门有部门编号(dept_id)、部门名称、部门简介等信息。
员工信息表 :每个员工有员工编号、姓名、部门编号。列出部门编号后就不能再将部门名称、部门简介等与部门有关的信息再加入员工信息表中。
如果不存在部门信息表,则根据第三范式(3NF)也应该构建它,否则就会有大量的数据冗余。
举例2:
商品类别名称依赖于商品类别编号,不符合第三范式。
修改:
表1:符合第三范式的 商品类别表 的设计
表2:符合第三范式的 商品表 的设计
商品表goods通过商品类别id字段(category_id)与商品类别表goods_category进行关联。
举例3:
球员player表 :球员编号、姓名、球队名称和球队主教练。现在,我们把属性之间的依赖关系画出来,如下图所示:
你能看到球员编号决定了球队名称,同时球队名称决定了球队主教练,非主属性球队主教练就会传递依赖于球员编号,因此不符合 3NF 的要求。
如果要达到 3NF 的要求,需要把数据表拆成下面这样:
二、反范式化
1、概述
规范化 vs 性能
- 为满足某种商业目标 , 数据库性能比规范化数据库更重要
- 在数据规范化的同时 , 要综合考虑数据库的性能
- 通过在给定的表中添加额外的字段,以大量减少需要从中搜索信息所需的时间
- 通过在给定的表中插入计算列,以方便查询
2、应用举例
举例1:
员工的信息存储在 employees 表 中,部门信息存储在 departments 表 中。通过 employees 表中的 department_id字段与 departments 表建立关联关系。如果要查询一个员工所在部门的名称:
select employee_id,department_name from employees e join departments d on e.department_id = d.department_id;
如果经常需要进行这个操作,连接查询就会浪费很多时间。可以在 employees 表中增加一个冗余字段-department_name,这样就不用每次都进行连接操作了。
举例2:
反范式化的 goods商品信息表 设计如下:
3、反范式的新问题
- 存储 空间变大 了
- 一个表中字段做了修改,另一个表中冗余的字段也需要做同步修改,否则 数据不一致
- 若采用存储过程来支持数据的更新、删除等额外操作,如果更新频繁,会非常 消耗系统资源
- 在 数据量小 的情况下,反范式不能体现性能的优势,可能还会让数据库的设计更加 复杂
4、反范式的适用场景
当冗余信息有价值或者能 大幅度提高查询效率 的时候,我们才会采取反范式的优化。
三、第四范式
举例:
比如我们建立课程、教师、教材的模型。我们规定,每门课程有对应的一组教师,每门课程也有对应的一组教材,一门课程使用的教材和教师没有关系。我们建立的关系表如下:
课程ID,教师ID,教材ID;这三列作为联合主键。
为了表述方便,我们用Name代替ID,这样更容易看懂:
这个表除了主键,就没有其他字段了,所以肯定满足BC范式,但是却存在 多值依赖 导致的异常。
假如我们下学期想采用一本新的英版高数教材,但是还没确定具体哪个老师来教,那么我们就无法在这个表中维护Course高数和Book英版高数教材的的关系。
解决办法是我们把这个多值依赖的表拆解成2个表,分别建立关系。