数据库基础概念与范式反范式总结
文章目录
- 一、基本概念
- 1、属性
- 2、元组
- 3、关系
- 4、超键
- 5、候选键
- 6、主键
- 7、主属性
- 8、外键
- 9、函数依赖
- 完全依赖
- 二、数据库范式
- 1、第一范式(1NF)
- 2、第二范式(2NF)
- 3、第三范式(3NF)
- 4、巴斯-科德范式(BCNF)
- 5、第四范式(4NF)
- 6、第五范式(5NF)
- 三、反范式
- 四、总结
一、基本概念
我们通过下面这个学生表来深入理解下,假设姓名没有重名的
学生表:姓名,性别,年龄,是否成年,身份证号码,手机号码,学号,班级,学生所在班级中的座位号,班主任
1、属性
属性就是字段,我们表中的每一列
2、元组
元组就是表中的每行数据(即数据库表中的每条记录),在二维表里,元组也称为行。
3、关系
关系(Relation)是指一个表(Table),它由行(Rows)和列(Columns)组成。
4、超键
超键,又叫超码,是能够唯一标识关系中的每个元组的一个或多个属性的集合,也就是在关系中能唯一标识记录的属性集。
超键可以包含多个属性,但不一定是最小的,超键+任何属性=超键
超键的分类:
- 单属性:表中的某个属性
- 组合:由多个属性组成
- 唯一性约束超键:通过在属性上添加唯一性约束,使其成为超键
例如,有一个学生表(学号,姓名,性别,年龄,身份证,班级),那么{学号}、{身份证}、{学号, 姓名}、{学号, 性别}等都是超键,{姓名},{姓名,性别}不是超键。
5、候选键
候选键,又叫候选码,是最小的超键,不含有多余属性的超键,也就是一个属性可以表示超键的话,就没必要使用多个属性。
在一个关系中,可能存在多个候选键
特点:
- 唯一性:候选键的值在关系中是唯一的,没有重复的记录。
- 最小性:候选键是最小的属性集合,即不能再删除任何一个属性而保持唯一性。
例如,还是以学生表(学号,姓名,性别,年龄,身份证,班级)来说,{学号}、{身份证}都是候选键,因为它唯一标识每个学生;{学号, 性别}不是候选键,因为它包含了多余属性。
6、主键
主键,又叫主码,是从候选键中选择的一个键,用于唯一标识关系中的每个元组。
主键必须是唯一且非空的。在关系中,只能有一个主键。
例如,在学生表中,{学号}、{身份证}都可以作为主键。
注:还是要根据场景,来定主键,比如身份证,一般在实际生产中,我们不用它当主键。
7、主属性
主属性,是指在主键中的属性,它们是用来唯一标识每个元组的关键属性。
如果主键包含多个属性,那么这多个属性都是主属性。
例如,在学生表中,{学号}是主键,因此它也是主属性。
8、外键
外键,又叫外码,是指其它表的主键。
例如,在学生表中,{班级}是外键,因为它是班级表的主键
9、函数依赖
一个属性的值(或属性集合的值)对于另一个属性的值(或属性集合的值)具有决定性影响,即给定一个属性(或属性集合)的值,可以唯一确定另一个属性(或属性集合)的值
例如,如果属性A的值决定了属性B的值,可以表示为 A -> B。这意味着在给定A的值的情况下,可以唯一确定B的值。
完全依赖
如果一个属性(或属性集合)对于另一个属性(或属性集合)的值具有完全依赖,那么没有任何冗余的属性可以从该依赖中删除,否则将无法唯一确定被依赖的属性(或属性集合)的值。
例如,假设有一个关系模式R(A, B, C),其中属性A和属性B的组合决定了属性C的值。如果删除属性A或属性B中的任何一个,都无法唯一确定属性C的值,那么我们可以说属性C对于属性A和属性B具有完全依赖。
二、数据库范式
主要有第一范式、第二范式、第三范式、巴斯-科德范式,第四范式和第五范式,前面是后续范式的基础,级别越高,数据库越标准。
1、第一范式(1NF)
1NF=First Normal Form
强调属性都是原子的,不可再拆分
例如,学生表(学号,姓名,班级,学生所在班级中的座位号,班主任,性别,年龄,是否成年,身份证号码),这个表设计符不符合第一范式?
这种得看业务场景了,如果需要展示xx姓同学,比如黄同学,李同学,欧阳同学这种,是不是就不符合,因为姓可能有多个字,比如欧阳索隆,欧阳修,你怎么知道姓欧还是欧阳,这种根本无法拆分,所以,需要把姓和名拆开存,不然不好展示,代码逻辑也比较复杂,所以这里的姓名还可以再拆分,就不符合第一范式了。
2、第二范式(2NF)
非主键属性完全依赖于主键,消除部分依赖
。
假设(A,B)是主键,完全依赖指的是(A,B) ->(C),部分依赖指的是(A)->(C)。
还是以学生表(学号,姓名,班级,学生所在班级中的座位号,班主任,性别,年龄,是否成年,身份证号码)为例,这个表设计符不符合第二范式?
{班级,学生所在班级中的座位号}是主键,但{班主任}由班级决定,没有完全依赖于主键,不符合第二范式,而且会有性能影响,这里数据冗余了,可能导致数据不一致,如果班主任有变更,很多学生记录都要同步修改,不然就出现了数据不一致。
解决方案:拆表,班主任字段拆出去
学生表(学号,姓名,班级,学生所在班级中的座位号,性别,年龄,是否成年,身份证号码)
班级表(班级,班主任)
3、第三范式(3NF)
非主键属性不传递依赖于主键,直接依赖于主键,消除传递依赖
假设A是主键,存在A->B->C,那么说C传递依赖于A。
例如,前面满足第二范式的表结构如下,这个表设计符不符合第三范式?
学生表(学号,姓名,班级,学生所在班级中的座位号,性别,年龄,是否成年,身份证号码)
班级表(班级,班主任)
年龄,是否成年,身份证号码,性别,都是非主键列,“年龄”和“性别”都可以由“身份证号码”推出,“是否成年”可以由“年龄”推出,所以不符合第三范式
解决方案:拆表,把年龄,是否成年,身份证号码拆出去
学生表(学号,姓名,班级,学生所在班级中的座位号,身份证号码)
班级表(班级,班主任)
身份证号码关系表(身份证号码,年龄,性别)
年龄关系表(年龄,是否成年)
上面这种场景,在实际环境中,需要维护多一些表或者Java代码进行判断,都有性能消耗,代码的话,每次查询的时候,代码都要计算1次,那么我们可以采取物化视图,插入年龄的时候,直接计算好,提升性能,具体实现可以参考数据库对象介绍与实践:视图、函数、存储过程、触发器和物化视图
4、巴斯-科德范式(BCNF)
对第三范式的优化,在它基础上,消除对主键子集的依赖而得到的,即非主键属性完全依赖于候选键
。
学生表(学号,姓名,班级,学生所在班级中的座位号,身份证号码)
班级表(班级,班主任)
身份证号码关系表(身份证号码,年龄,性别)
年龄关系表(年龄,是否成年)
这个设计符不符合巴斯-科德范式?
学生所在班级中的座位号完全依赖于{学号,班级},而不依赖于学号,所以符合
5、第四范式(4NF)
要求消除非平凡多值依赖。
假设有一个关系表格包含以下列:学生ID、课程ID、学生成绩1、学生成绩2。如果每个学生ID和课程ID的组合可以决定多个学生成绩的值,而不是只有一个固定的学生成绩值,那么就存在一个非平凡多值依赖。
6、第五范式(5NF)
要求消除非平凡函数依赖。
假设有一个关系表格包含以下列:学生ID、学生姓名、学生年龄。如果每个学生ID都唯一确定一个学生姓名,那么学生ID对学生姓名存在一个非平凡函数依赖。因为在现实生活中,学生ID并不直接决定学生姓名,而是通过其他信息或逻辑来确定。
三、反范式
反范式(Denormalization)是一种数据库设计技术,旨在提高数据库的性能和查询效率,但可能会牺牲一部分数据的一致性和完整性。
在范式化的数据库设计中,数据被分解为多个表,以减少数据冗余和提高数据的一致性。然而,范式化的数据库结构可能导致在进行复杂查询时需要进行多个表的连接操作,从而影响查询性能。
反范式化通过将分解的表重新合并或添加冗余数据,以减少表之间的连接操作,从而提高查询性能。这样可以简化查询的复杂性,减少查询的执行时间。
导致的问题:
- 增加存储空间,数据冗余字段
- 增大更新风险,更新时,需要确保所有相关的冗余数据都得到正确的更新,以保持数据的一致性
四、总结
在实际工作中,一般遵守1NF、2NF、3NF即可,但一般用反范式,可以显著提高性能优势,我们需要自己权衡下,根据具体的应用场景和性能需求来决定使用啥范式。
经验之谈:
- 设计的时候,脑子里要有范式,用于指导设计
- 遵守范式,然后根据业务,再做反范式