数据库范式
第一范式(1NF)
第一范式要求数据库表的每一列都是不可分割的基本数据项,即表中的字段值必须是原子的、不可再分的。换句话说,表中的所有字段值都应该是单一的,而不是集合、数组或记录等复合数据类型。这是数据库设计中最基本的要求,任何关系型数据库都应该满足第一范式。
第二范式(2NF)
第二范式建立在第一范式的基础上,它要求表必须有一个主键,且表中的非主键列必须完全依赖于主键。所谓完全依赖,是指非主键列不能仅依赖于主键的一部分(比如主键是复合主键时)。如果表中存在部分依赖,则不满足第二范式,此时应该将表拆分为两个或多个表,以消除部分依赖。
第三范式(3NF)
第三范式建立在第二范式的基础上,它进一步要求表中的非主键列必须直接依赖于主键,而不能存在传递依赖。传递依赖是指非主键列依赖于另一个非主键列,而这个非主键列又依赖于主键。如果表中存在传递依赖,则不满足第三范式,这通常会导致数据冗余和更新异常。为了消除传递依赖,需要将表进一步拆分,使得每个表中的非主键列都直接依赖于主键。
第一范式,
列属性必须不可分割,(基础和绩效可以合并为工资列,但具体的工资可以抽出一张表独立维护)不能有小表存在。
学号 | 姓名 | 年龄 | 绩效 | 基础工资 | 邮箱 |
---|---|---|---|---|---|
1111 | 张三 | 11 | 1344 | 12 | zhangsan.@huawei.email |
2222 | 李四 | 23 | 122 | 31 | lisi.@huawei.email |
3333 | 王五 | 44 | 444 | 144 | wangwu.@huawei.email |
合并工资后,可以对工资更加详尽的记录,
- 学生信息表,
学号 | 姓名 | 年龄 | 工资 | 邮箱 |
---|---|---|---|---|
1111 | 张三 | 11 | 工资ID | zhangsan.@huawei.email |
2222 | 李四 | 23 | 工资ID | lisi.@huawei.email |
3333 | 王五 | 44 | 工资ID | wangwu.@huawei.email |
2.工资信息表,
工资ID | 学号 | 基础工资 | 绩效 | 奖金 | 扣除工资 |
---|---|---|---|---|---|
工资ID | 1111 | 12112 | 11 | 233 | 222 |
工资ID | 2222 | 1212 | 23 | 32 | 333 |
工资ID | 3333 | 21212 | 44 | 1221 | 111 |
可以看出第一范式强调的是,存在小表就需要通过外间独立维护。
第二范式,
第一范式基础上,表中的非主属性必须完全依赖某一候选健。即,表中不能存在联合主键,不能有另外的表合并进主表,因为我们完全可以将成绩表合并给学生表从和实现成绩的查询。
学号 | 姓名 | 年龄 | 成绩 | 课程 |
---|---|---|---|---|
1111 | 张三 | 11 | 99 | 数学 |
2222 | 李四 | 23 | 100 | 语文 |
3333 | 王五 | 44 | 40 | 英语 |
分解后
- 学生信息表,
学号 | 姓名 | 年龄 |
---|---|---|
1111 | 张三 | 11 |
2222 | 李四 | 23 |
3333 | 王五 | 44 |
2,成绩表
学号 | 课程ID | 成绩 |
---|---|---|
1111 | 222 | 11 |
2222 | 111 | 23 |
3333 | 222 | 44 |
可以看出第二范式强调的是,存在的联合主键就说明可以独立维护成一张表。往往这张表是中间表,存储数据全是ID。
第三范式,
第二范式基础上,要求所有非主属性不依赖于其他非主属性。即,数据库中的每一列都可以由主键决定而不是其他列可以推导的。或者说数据库的每一列都和主属性直接相关,而不存在传递依赖。
学号 | 姓名 | 系主任 | 系名称 |
---|---|---|---|
1111 | 张三 | 主任A | 新闻系 |
2222 | 李四 | 主任B | 语言系 |
3333 | 王五 | 主任C | 历史系 |
其中系主任可以由系号推到而出,系号由学号推到而出。所以存在传递来,那就必须将系信息表独立维护了,
- 学生信息表,
学号 | 姓名 | 系ID |
---|---|---|
1111 | 张三 | 11 |
2222 | 李四 | 23 |
3333 | 王五 | 44 |
2,系信息表
系ID | 系名称 | 系主任 |
---|---|---|
1111 | 新闻系 | 李时珍 |
2222 | 历史系 | 王维 |
3333 | 语言系 | 李清照 |
BC范式
第三范式基础上,尽量避免数据冗余和不一致,提高可靠性和完整性
仓库ID | 存储物品ID | 管理员ID | 数量 |
---|---|---|---|
1111 | 2222 | 3131 | 1313 |
2222 | 1121 | 133 | 1331 |
3333 | 113331 | 13113 | 133 |
一个管理员只在一个仓库工作,一个仓库存在多个存储物品,该表满足第三范式,但是仍存在如下问题,
- 异常删除, 当某仓库物被清空后,就需要将存储物品和管理员清除,其实这也顺带清楚了管理员和仓库之间的关系,真是系统中往往管理员是不会频繁改变的。 比如 小明管理仓库A。
- 插入异常,反之亦然,当仓库没有货物时,无法建立仓库与管理员的关系。
- 更新异常, 当仓库更换管理员时,所有相关的行记录都需要更新。
这就需要对表进行拆解,
- 仓库货物信息表
仓库ID | 存储物品ID | 数量 |
---|---|---|
1111 | 2222 | 1313 |
2222 | 1121 | 1331 |
3333 | 113331 | 133 |
- 仓库管理员关联信息表
仓库ID | 管理员ID |
---|---|
1111 | 2222 |
2222 | 1121 |
3333 | 113331 |
再看上述异常就会被消除,当删除货物时,管理员信息保持独立,当插入管理员和仓库信息时,无需货物信息存在,当更新管理员信息时,货物表不受影响。
第五范式
第五范式(5NF)也被称为完美范式。它要求关系模式R的依赖关系完全由R的候选码所隐含,即属性均为候选码。第五范式旨在通过分隔语义连接的关系来存储多值事实,以减少关系数据库中的冗余。
在实际应用中,第五范式的应用较少,因为它涉及到复杂的表分解和重组,可能会导致查询变得更加复杂。然而,在一些特定情况下,第五范式仍然有其价值。例如,在一个大型复杂的数据库系统中,存在大量的关系模式和数据依赖关系,通过使用第五范式,可以更好地管理和维护这些复杂的数据模型,并提高数据库系统的性能和可靠性。
总的来说,第五范式是一种高级形式的实体完整性,可以帮助数据库系统更好地管理和维护大型复杂的数据模型。尽管它在日常使用中不如第三范式常见,但它在处理特定类型的数据模型时仍然非常有用。
反范式
数据库范式的本质是规范化,通过规范化可以有效的避免一些冗余甚至是一些错误的产生。
然而,真实的环境中往往不是完美的规范,或者说遵循完美不一定是正确的。真实的场景中,客户或者系统是需要关注性能的,所以就需要反规范化的一些设计去提升性能,这也就是为什么会有反范式的存在。
通过合理的反范式设计,可以有效地
- 降低连接操作的需求
- 降低外键和索引的数目
- 减少表的数目
从而提高查询效率。
反范式的方法
- 增加冗余列:再多个表中,都增加相同的列,从而避免获取某些信息时的连表操作。
- 增加派生列:在表中增加可以由别的表计算而来的列。
- 重新组表:如果两张表经常需要连接在一些查看所有内容,则将两张表合并为一张大表。
- 水平分割:数据规模过大时,可以将同一张表的数据分隔开存放在不同的表(Student1,Student2,Student3,)中。
- 垂直分割:对于列过多的表,将不同列分割到不同的表中,主键串联两张表。(student, student_extend)
带来的其他问题
- 数据冗余:反范式设计会引入冗余数据,这可能会导致数据不一致性和数据更新时的额外开销。
- 更新异常:当修改反范式表中的数据时,可能需要在多个地方进行修改,这可能会导致更新异常。
- 存储空间浪费:反范式会引入冗余数据,因此可能会浪费存储空间。
- 查询性能提升有限:在数据量小的情况下,反范式不能体现性能的优势,可能还会让数据库的设计更加复杂。
- 维护成本增加:由于数据冗余,数据维护成本更高,特别是在需要更新大量冗余数据时。
反范式缺点的解决方案
然而,反范式设计可能会引入数据冗余,导致数据不一致性和数据更新时的额外开销。以下是针对反范式设计缺点的解决方案:
数据清洗:定期进行数据清洗,以确保数据的准确性和一致性。这包括识别和纠正错误数据、去除重复数据等。
数据同步机制:建立有效的数据同步机制,确保所有冗余数据在更新时都能及时反映变化。
索引优化:通过合理的索引设计,减少查询时需要扫描的数据量,提高查询效率。
分区和归档:对于历史数据,可以进行分区和归档处理,以减少对当前数据的影响。
事务隔离:在处理冗余数据时,确保事务隔离级别足够高,防止数据不一致。
监控和报警:实施实时监控,一旦检测到数据不一致,立即发出警报并采取措施。
数据治理:建立健全数据治理体系,制定明确的数据管理政策和流程,确保数据的质量和安全。