在处理数据库时,常常会遇到诸如冗余数据和不一致更新等问题。第二范式是一个数据库规范化步骤,它在第一范式(1NF)的基础上构建,以创建更清洁和高效的表格。
了解2NF对于任何从事数据库设计或数据管理工作的人都至关重要,它为像第三范式(3NF)这样的更高规范化形式奠定了基础。在本文中,我们将探讨2NF的工作原理,以及如何转换表格以满足2NF的要求,并提供实际示例。我们还将讨论2NF的优缺点,以及最适合的使用场景。
理解第二范式
第二范式是一个专注于消除部分依赖关系的数据库规范化步骤。它是由关系数据库的先驱埃德加·科德(Edgar F. Codd)引入的,作为他规范化工作的一部分。
在表格能够达到2NF之前,必须满足第一范式的规则:
- 原子性:每个单元格必须包含一个单一的值(不能有重复的组或数组)。
- 唯一行:表必须有一个明确的主键。
第二范式进一步增加了一条规则:消除部分依赖。
部分依赖发生在一个非主属性(不是任何候选键的列)仅依赖于复合键的一部分而不是整个键时。2NF规则确保所有非主属性依赖于整个主键,而不仅仅是其中的一部分。在表中保留部分依赖意味着冗余数据可能会进入数据库,在更新或删除过程中可能导致低效和潜在的不一致。
理论本身可能有点枯燥,让我们看一个实际的例子。
以下是 Datacamp 学生的课程注册表。
Student ID | Course ID | Course Name | Instructor Name |
---|---|---|---|
1001 | 201 | SQL基础 | Ken Smith |
1002 | 202 | Python简介 | Merlin O’Donnell |
1001 | 202 | Python简介 | Merlin O’Donnell |
这里,主键是学生ID和课程ID的组合。然而,非主属性课程名称和课程费用仅依赖于课程ID,而不是整个键。这违反了2NF。
将表分解为达到2NF的步骤:
为确保表符合2NF的规则,您需要:
- 识别所有候选键:确定能唯一标识表中行的属性最小集合。这些就是您的候选键。
- 确定函数依赖关系:识别表中的所有函数依赖关系。具体来说,查找那些非主属性(不是任何候选键的一部分)仅依赖于复合键的一部分的依赖关系。
- 消除部分依赖:对于每个部分依赖:
- 将依赖属性与其依赖的键的部分放入新表中。
- 确保新表具有唯一的主键。
- 重复直到没有部分依赖剩余:确认所有表中每个非主属性是否完全依赖于其相应的主键。
实践中第二范式的示例
现在让我们看两个示例。
示例1:课程报名表
早些时候,我们看到了以下课程报名表:
Student ID | Course ID | Course Name | Instructor Name |
---|---|---|---|
1001 | 201 | SQL基础 | Ken Smith |
1002 | 202 | Python入门 | Merlin O’Donnell |
1001 | 202 | Python入门 | Merlin O’Donnell |
让我们按照前一节中概述的步骤进行。
1. 确定我们的候选键。
在这种情况下,候选键是由学生ID和课程ID组成的复合键。这个唯一的组合识别表中的每一行。
2. 确定我们的功能依赖关系
课程名称 和 讲师名称 依赖于 课程ID,而不是完整的复合键(学生ID, 课程ID)。这是一个部分依赖,因为这些属性仅依赖于复合键的一部分。
3. 消除部分依赖
我们需要将仅依赖于关键部分(课程名称和教师姓名)的属性移至一个仅基于课程ID的新表中。
分解后,我们的新表如下:
课程报名表
Student ID | Course ID |
---|---|
1001 | 201 |
1002 | 202 |
1001 | 202 |
课程详情表
如果您想动手创建自己的数据库,请查看我们的PostgresQL课程。如果您有一定的基础,可以尝试这个雪花数据建模入门,其中涵盖了实体关系和维度建模等概念。
示例2:订单表
我们将从这个订单表开始。尝试按照我们上面概述的步骤,自行分解这个表格!
Order ID | Product ID | Order Date | Product Name | Supplier Name |
---|---|---|---|---|
1 | 201 | 2024-11-01 | 笔记本电脑 | TechSupply |
1 | 202 | 2024-11-01 | 鼠标 | TechSupply |
2 | 201 | 2024-11-02 | 笔记本电脑 | TechSupply |
3 | 203 | 2024-11-03 | 键盘 | KeyMasters |
1. 确定我们的候选键
订单ID和产品ID的组合唯一标识每一行,使得(订单ID,产品ID)成为复合候选键。因为没有单个列可以唯一标识行:
- 订单编号本身并不唯一,因为同一个订单中可以包含多个产品。
- 产品编号本身并不唯一,因为同一产品可能出现在不同的订单中。
这意味着 (订单 ID, 产品 ID) 也是我们的主键。
2. 确定我们的功能依赖关系
订单日期取决于订单编号(而不是完整的复合键)。这是部分依赖。
产品名称 和 供应商名称 依赖于 产品ID(而不是完整的复合键)。这些也是部分依赖。
3. 消除部分依赖
我们需要将表拆分为更小的表,每个表解决一个逻辑依赖。
首先,我们将创建一个订单信息表,包含与订单ID相关的信息。
订单表
Order ID | Order Date |
---|---|
1 | 2024-11-01 |
2 | 2024-11-02 |
3 | 2024-11-03 |
然后,我们创建一个表,包含与产品ID相关的信息。
订单表
Product ID | Product Name | Supplier Name |
---|---|---|
201 | 笔记本电脑 | 科技供应 |
202 | 鼠标 | 科技供应 |
203 | 键盘 | 键大师 |
原始表现在简化为仅包含复合键以及订单与产品之间的关系。
Order ID | Product ID |
---|---|
1 | 201 |
1 | 202 |
2 | 201 |
3 | 203 |
现在,我们的数据库处于第二范式,因为 1) 所有部分依赖关系已被消除,且 2) 非主属性完全依赖于各自的主键。
何时实施第二范式
那么,为什么你应该将数据库重构为第二范式(2NF)?它单独足够吗,还是应该更进一步,追求第三范式(3NF)?
第二范式的好处和局限性
第二范式提供了几个优点,使其成为数据库规范化过程中的一个有用步骤:
- 增强的数据完整性:通过消除部分依赖,2NF 最小化插入、更新和删除异常,从而导致更可靠的数据库。
- 减少冗余:2NF 减少数据重复,优化存储使用并简化数据维护。
- 改进的数据结构:通过创建更清晰、更高效的数据库设计,为进一步规范化(如过渡到第三范式)奠定了基础。
但它确实存在一些限制:
- 增加的复杂性:为了满足2NF而分解表可能会使设计过程变得更加复杂,特别是在处理复合键和依赖关系时。
- 附加联接:拆分表可能需要在查询中进行更多的联接,在有大型数据集或复杂查询的系统中可能会影响性能 – 详细信息如下。
- 残余冗余:虽然2NF减少了部分依赖关系,但它并未解决传递依赖关系,直到在3NF中解决之前仍会存在一些冗余。
第二范式的性能考虑
将表进行分解以消除部分依赖关系可能直接影响数据库性能。一方面,实现2NF可以减少数据冗余并提高一致性,减少在插入、更新或删除操作期间的异常。另一方面,规范化可能会增加表的数量,这意味着在检索相关数据时需要进行额外的连接。这可能会影响大型数据集的查询性能。
为了确保您的规范化数据库保持高性能,请确保遵循以下最佳实践:
- 索引:使用索引加快分解表之间的连接速度。
- 查询优化: 优化查询以最小化额外连接的成本。
- 混合方法: 在性能重要的领域,如报表表中,将规范化与去规范化结合起来。
- 定期监控: 使用性能分析工具持续评估数据库性能,以发现潜在问题。
2NF只是实现第三范式的过渡步骤吗?
在大多数情况下,数据库设计师努力实现第三范式,因为它能够进一步减少冗余并提高整体数据完整性。然而,实现3NF通常需要额外的工作,例如创建更多的表和关系,这可能会在查询执行中引入复杂性和性能权衡。
在某些情况下,仅使用第二范式可能就足够了。如果简洁性和快速实施是优先考虑的因素,例如在小规模项目、原型设计或数据冗余最小的情况下,2NF可能足够。例如,在所有属性已经完全依赖于一个简单主键的系统中,实现2NF可能会实现减少部分依赖的主要目标,而无需进一步规范化。
超越第二范式:迈向第三范式
如果您想进一步规范化数据库,可以继续重构表以达到第三范式。
3NF通过解决传递依赖来构建在2NF之上 – 即非关键属性依赖于其他非关键属性而不是主键的情况。这种进展确保每个属性直接依赖于主键而不依赖于其他内容。
例如,在跟踪课程注册情况的表中:
- 第二范式: 确保诸如课程名称和学生名称等属性完全依赖于各自的主键(例如,学生ID 和 课程ID)。这消除了部分依赖,即非主键属性仅依赖于复合键的一部分。
- 3NF:确保如讲师详细信息或部门信息等属性存储在单独的表中,消除传递依赖。
3NF 适用于数据完整性和效率至关重要的更复杂系统,特别是当数据量增长时。如果你想了解更多关于 3NF 及其更严格形式 BCNF 的信息,请查看我们的 什么是第三范式? 文章。
结论
第二范式是数据库规范化的重要步骤,弥合了 1NF 和更高形式如 3NF 之间的差距。通过消除部分依赖,2NF 减少了冗余,提高了数据的可靠性。虽然它可能增加一些复杂性,但改进的数据完整性和简化的维护所带来的好处,使其成为有效数据库设计的关键部分。
如果您准备进一步提升自己的技能,可以探索我们的 数据库设计 课程,以加深对规范化技术及其实际应用的理解。您还可以通过我们的 SQL 助理认证 来验证您的 SQL 和数据库管理技能,并向潜在雇主展示您的专业知识!
最后,我想说,如果您是企业中的决策者,并且知道您需要在创建 更干净、更高效的数据库 上付出努力,请考虑提交 DataCamp for Business 演示请求。我们可以帮助提升您团队的能力,以便您能够创建可扩展的数据库系统,从而推动业务效率和创新。我们甚至可以创建量身定制的学习路径和定制课程。
Source:
https://www.datacamp.com/tutorial/second-normal-form