规范化
计算机科学· 30 分钟阅读
1. 规范化的目的与数据异常★★☆☆☆⏱ 10 min
规范化是在关系数据库中组织数据的系统化过程,目的是减少冗余数据存储,消除不良的数据异常。它将大型非结构化表拆分为更小、连接良好的表,保持数据一致性。
数据异常
插入、更新或删除记录时,因冗余数据产生的意外不一致。主要有三种类型:插入异常、删除异常和更新异常。
例:
将学生姓名和课程细节存储在同一个表中,会导致学生姓名在多个课程中重复存储。
- 更新异常:修改学生姓名需要更新该学生的每一行,如果遗漏某一行就会导致不一致。
- 插入异常:在至少有一个学生选修该课程之前,你无法向数据库添加新课程。
- 删除异常:删除某课程的最后一个注册学生时,会意外删除该课程本身的所有记录。
识别以下场景中的异常类型:一个表存储 (OrderID, CustomerID, CustomerName, CustomerAddress, ProductID, ProductName)。如果某个客户的所有订单都被删除,该客户的联系信息也会丢失。命名异常并解释其发生原因。
- 1
这是删除异常,由客户数据的冗余存储导致。
- 2
客户详情函数依赖于CustomerID(客户的唯一标识符),而非OrderID(订单的唯一标识符)。这意味着同一客户的每个订单都会重复存储客户数据。
- 3
当某个客户的所有订单都被删除后,表中不再有包含该客户详情的行,因此数据被意外丢失。
Exam tip:
CIE考官通常会要求你在给定场景中命名并解释异常,而不只是回忆定义。一定要将异常与冗余数据存储联系起来。
2. 第一范式和第二范式★★★☆☆⏱ 15 min
规范化是逐步应用的,每个范式都比前一个增加了更严格的规则。大多数CIE考题要求规范化到3NF,因此按步骤顺序操作非常重要。
第一范式 (1NF)
如果关系的所有属性都只包含原子(不可分割)值,且不存在重复数据组,则该关系符合1NF。
例:
在学生的单个单元格中存储多个电话号码的表不符合1NF。
第二范式 (2NF)
如果关系符合1NF,且所有非键属性都完全函数依赖于整个主键(不存在部分依赖),则该关系符合2NF。2NF仅适用于具有复合主键的关系。
例:
如果主键是 (StudentID, CourseID),StudentName 仅依赖于 StudentID(主键的一部分),这就是违反2NF的部分依赖。
将以下未规范化关系转换为1NF,再转换为2NF:一个学生可以选修多门课程。未规范化关系:Student(StudentID, StudentName, StudentEmail, CourseID, CourseName)。
- 1
首先,分解每个学生的重复课程数据组,得到带有复合主键的1NF:
- 2\text{Student_1NF (StudentID, StudentName, StudentEmail, CourseID, CourseName)}
- 3
接下来,识别部分依赖:
StudentName, StudentEmail仅依赖于StudentID,CourseName仅依赖于CourseID。两者都是对复合主键(StudentID, CourseID)的部分依赖。 - 4
拆分出三个关系消除部分依赖,得到2NF:
- 5
检查你对2NF规则的理解:
以下关于2NF的陈述哪一个是正确的?
2NF适用于所有关系,无论主键类型是什么
单属性主键的关系自动符合2NF
2NF消除传递依赖
2NF允许重复组
显示答案
1 —正确。部分依赖仅在主键是复合主键时存在,因此单属性主键意味着所有非键属性都完全依赖于整个主键。
3. 第三范式和BCNF★★★★☆⏱ 20 min
完成2NF后,下一步是3NF,这是CIE考试中规范化最常要求的最终目标。博伊斯-科德范式(BCNF)是3NF的更严格扩展,用于处理更复杂的依赖情况。
第三范式 (3NF)
如果关系符合2NF,且没有非键属性传递依赖于主键,则该关系符合3NF。所有非键属性必须仅依赖于主键,不能依赖于其他非键属性。
博伊斯-科德范式 (BCNF)
如果关系符合3NF,且对于每个非平凡函数依赖 , 都是该关系的超键,则该关系符合BCNF。它解决了非键属性决定主键一部分的依赖问题。
将以下2NF关系转换为3NF:Course(CourseID, CourseName, TutorID, TutorName, Department)。主键 = CourseID。
- 1
首先,识别函数依赖:
TutorID \rightarrow TutorName, Department。这是传递依赖,因为TutorID是依赖于主键CourseID的非键属性,因此TutorName和Department通过TutorID依赖于CourseID。 - 2
拆分出两个关系消除传递依赖,得到3NF:
- 3
- 4
检查BCNF:每个函数依赖的左侧都是超键,因此两个关系也都符合BCNF。
Exam tip:
除非题目明确要求BCNF,否则停止在3NF即可。额外工作不会扣分,但会浪费宝贵的考试时间。
4. 反规范化:权衡★★★☆☆⏱ 8 min
规范化并不总是最优的最终数据库设计。反规范化是在已规范化数据库中有意引入冗余以提升性能的操作。
反规范化
将更高范式的关系合并的过程,目的是减少常见查询所需的连接次数,代价是增加冗余,提高异常风险。
- 优势:读查询更快,因为检索常用数据所需的连接次数更少
- 常见用例:数据仓库、报表系统和读密集型应用
- 代价:更高的存储需求,更新时避免数据不一致的逻辑更复杂
举一个设计师会选择对3NF数据库进行反规范化的例子。
- 1
电商网站在客户订单历史中,每条订单都会显示商品名称,会选择反规范化来提升性能。
- 2
规范化设计每次加载订单历史都需要将
Order表和Product表连接,这是一个高频操作。 - 3
将商品名称直接存储在
Order表中消除了连接需求,加快了终端用户的查询响应速度,尽管商品名称被冗余存储。
5. 常见陷阱
错误做法:
要求规范化到3NF时停止在1NF或2NF,未解决依赖问题
原因:
很多考生忘记规范化是增量过程,每个范式都要求首先满足更低范式的所有规则
正确做法:
始终按顺序操作:1NF → 2NF → 3NF,进入下一步前检查每个规则
错误做法:
解释时混淆部分依赖(2NF)和传递依赖(3NF)
原因:
考生经常混淆违反不同范式的两种依赖类型的定义
正确做法:
记住:部分依赖 = 非键依赖于复合主键的一部分(2NF规则);传递依赖 = 非键依赖于另一个非键(3NF规则)
错误做法:
在一个单元格中保留多个值仍称其符合1NF,违反原子性要求
原因:
考生有时会赶时间,忘记1NF的核心规则是所有属性必须是原子的
正确做法:
拆分重复组为单独的行或单独的关系,确保1NF中每个单元格只存储一个值
错误做法:
声称反规范化始终是不良实践,绝不应该使用
原因:
规范化旨在减少异常,但它不是所有用例的最优选择
正确做法:
将反规范化视为读密集型系统的有意设计选择,其性能提升超过冗余的代价
6. 速查表
范式 | 核心要求 |
|---|---|
未规范化 | 包含重复组或非原子值 |
1NF | 所有属性原子;无重复组 |
2NF | 1NF + 无部分依赖(非键依赖于整个主键) |
3NF | 2NF + 无传递依赖(非键仅依赖于主键) |
BCNF | 3NF + 每个函数依赖的决定因素都是超键 |
真题中的出现
AI 根据考纲规律估算的考点位置,请对照官方真题核实准确性。仅作复习重点参考。
- 2022 · 2
将关系规范化为3NF
- 2023 · 2
识别并解释数据异常
- 2024 · 2
解释反规范化的目的
深入阅读
下一步
规范化是关系数据库的核心设计技能,建立在关系模型基础概念之上。掌握它可以确保你设计出一致、高效的数据库,避免冗余存储导致的常见数据异常。它是CIE A-Level 9618 试卷2中频繁考察的主题,因此练习将未规范化关系转换为3NF,提升考试速度非常重要。接下来,你可以继续学习如何用SQL实现规范化数据库设计,探索事务处理和并发控制,或是学习完整A-Level大纲中的高级数据库概念。
