在处理数据库时,常会遇到数据冗余和更新不一致等问题。第二范式是建立在第一范式(1NF)之上的数据库规范化步骤,用于构建更整洁、更高效的表。
对于从事数据库设计或数据管理的任何人来说,理解 2NF 至关重要,它也为更高阶的规范化形式(如第三范式,3NF)打下基础。本文将通过实际示例介绍 2NF 的工作原理以及如何将表格转换为满足 2NF 要求。我们还会讨论 2NF 的优缺点以及其最适用的场景。
理解第二范式
第二范式是以消除部分依赖为核心的数据库规范化步骤。它由关系型数据库的先驱 Edgar F. Codd 在其规范化研究中提出。
一张表要达到 2NF,必须首先满足第一范式的规则:
- 原子性: 每个单元格只能包含一个值(不能有重复组或数组)。
- 行唯一: 表必须有明确的主键。
在此基础上,2NF 还要求:消除部分依赖。
当某个非主属性(不属于任何候选键的列)仅依赖于复合键的一部分而非整个键时,就发生了部分依赖。2NF 规则确保所有非主属性都依赖于完整的主键,而不是其中某一部分。如果在表中保留部分依赖,冗余数据就可能渗入数据库,导致低效,并在更新或删除时引发潜在不一致。
光讲理论可能有点枯燥,我们来看一个实际例子。
下面是 DataCamp 学生的课程选课表。
这里,主键是学生 ID与课程 ID的复合。然而,非主属性课程名称和课程费用仅依赖于课程 ID,而不是整个键。这违反了 2NF。
分解表以实现 2NF 的步骤
要确保一张表遵循 2NF 的规则,您需要:
- 识别所有候选键: 确定能唯一标识表中行的最小属性集。这些就是候选键。
- 确定函数依赖: 识别表中的所有函数依赖。特别关注那些非主属性(不属于任何候选键)仅依赖于复合键部分而非整个键的依赖关系。
- 消除部分依赖: 对每个部分依赖:
- 将受其影响的属性与它们所依赖的键部分一起移动到新表中。
- 确保新表有唯一的主键。
- 重复直到不再存在部分依赖: 确认所有表中的每个非主属性都完全依赖其各自的主键。
第二范式的实践示例
现在我们来看两个示例。
示例 1:课程选课表
前面我们看到如下选课表:
我们按照上一节的步骤来操作。
1. 识别候选键
在该表中,候选键是由学生 ID与课程 ID组成的复合键。这个唯一的组合可以标识表中的每一行。
2. 确定函数依赖
课程名称和讲师姓名依赖于课程 ID,而不是完整的复合键(学生 ID,课程 ID)。这属于部分依赖,因为这些属性只依赖于复合键的一部分。
3. 消除部分依赖
我们需要将只依赖键部分的属性(课程名称和讲师姓名)移动到一个仅基于课程 ID的新表中。
分解后,我们的新表如下:
课程选课表
| 学生 ID | 课程 ID |
|---|
| 1001 | 201 |
| 1002 | 202 |
| 1001 | 202 |
课程详情表
示例 2:订单表
我们从这张订单表开始。试着按照上面的步骤自行分解这张表!
| 订单 ID | 产品 ID | 下单日期 | 产品名称 | 供应商名称 |
|---|
| 1 | 201 | 2024-11-01 | Laptop | TechSupply |
| 1 | 202 | 2024-11-01 | Mouse | TechSupply |
| 2 | 201 | 2024-11-02 | Laptop | TechSupply |
| 3 | 203 | 2024-11-03 | Keyboard | KeyMasters |
1. 识别候选键
订单 ID与产品 ID的组合可以唯一标识每一行,因此(订单 ID,产品 ID)构成一个复合候选键。没有任何单列可以唯一标识行,因为:
- 订单 ID 本身不唯一,因为同一订单可以包含多个产品。
- 产品 ID 本身不唯一,因为同一产品可以出现在不同订单中。
这意味着(订单 ID,产品 ID)也是我们的主键。
2. 确定函数依赖
下单日期依赖于订单 ID(而非完整的复合键)。这属于部分依赖。
产品名称和供应商名称依赖于产品 ID(而非完整的复合键)。这些同样是部分依赖。
3. 消除部分依赖
我们需要将该表拆分为更小的表,每个表对应一个逻辑依赖。
首先,我们创建包含订单 ID专属信息的订单信息表。
订单表
| 订单 ID | 下单日期 |
|---|
| 1 | 2024-11-01 |
| 2 | 2024-11-02 |
| 3 | 2024-11-03 |
接着,我们创建一个包含产品 ID专属信息的表。
订单表
| 产品 ID | 产品名称 | 供应商名称 |
|---|
| 201 | Laptop | TechSupply |
| 202 | Mouse | TechSupply |
| 203 | Keyboard | KeyMasters |
原始表现在仅保留复合键以及订单与产品之间的关联关系。
| 订单 ID | 产品 ID |
|---|
| 1 | 201 |
| 1 | 202 |
| 2 | 201 |
| 3 | 203 |
现在,我们的数据库已满足 2NF,因为 1)所有部分依赖都被消除;2)非主属性完全依赖各自的主键。
何时实施第二范式
那么,为什么要将数据库重构到 2NF?它本身是否足够,还是应该更进一步,目标指向 3NF?
第二范式的优势与局限
第二范式有多项优势,使其成为数据库规范化过程中有用的一步:
- 提升数据完整性: 通过消除部分依赖,2NF 将插入、更新和删除异常降至最低,从而使数据库更可靠。
- 减少冗余: 2NF 降低数据重复,优化存储使用并简化数据维护。
- 改进数据结构: 为进一步规范化(如推进到第三范式)奠定基础,营造更整洁、更高效的数据库设计。
但它也有一些局限:
- 复杂性增加: 为满足 2NF 而分解表会让设计过程更复杂,尤其是在涉及复合键和依赖关系时。
- 额外的连接: 表拆分后,查询可能需要更多连接,在数据量大或查询复杂的系统中可能影响性能——下文会有更多讨论。
- 残留冗余: 2NF 虽然减少部分依赖,但不处理传递依赖,仍会留下一些冗余,需在 3NF 中进一步解决。
第二范式的性能考量
为消除部分依赖而分解表会直接影响数据库性能。一方面,实现 2NF 可以减少数据冗余并提升一致性,从而在插入、更新或删除操作中更少出现异常。另一方面,规范化会增加表的数量,检索相关数据时需要额外的连接,这可能对大数据集中的查询性能造成影响。
为确保规范化后的数据库仍具备良好性能,请遵循以下最佳实践:
- 索引: 使用索引加速分解表之间的连接。
- 查询优化: 优化查询以尽量降低额外连接的成本。
- 混合方法: 在性能关键的区域(如报表表)将规范化与反规范化结合使用。
- 定期监控: 持续使用分析工具评估数据库性能,及时发现潜在问题。
2NF 只是迈向第三范式的过渡步骤吗?
在大多数情况下,数据库设计者会力求达到第三范式,因为它能进一步减少冗余并提升整体数据完整性。然而,实现 3NF 往往需要更多工作,例如创建更多的表和关系,这可能在查询执行中引入复杂性和性能权衡。
也有仅采用第二范式就足够的情况。如果以简洁和快速实施为优先,例如小型项目、原型阶段,或数据冗余极少的情形,2NF 可能已能满足需求。例如,在所有属性都已完全依赖于简单主键的系统中,实现 2NF 就能达成减少部分依赖的主要目标,而无需进一步规范化。
超越第二范式:迈向第三范式
如果您希望进一步规范化数据库,可以继续重构表直至达到第三范式。
3NF 建立在 2NF 之上,解决传递依赖——即非键属性依赖于其他非键属性而不是主键的情况。通过这种推进,确保每个属性都直接依赖于主键而非其他因素。
例如,在跟踪课程选课的表中:
- 2NF:确保课程名称和学生姓名等属性完全依赖于各自的主键(如学生 ID与课程 ID)。这消除了非键属性仅依赖复合键部分的部分依赖。
- 3NF:确保讲师详情或院系信息等存放于独立表中,消除传递依赖。
3NF 非常适合对数据完整性和效率有高要求的复杂系统,尤其是在数据量增长时。如果您想深入了解 3NF 及其更严格的形式 BCNF,欢迎阅读我们的文章 What is third normal form?。
结论
第二范式是数据库规范化中的关键一步,承上启下于 1NF 与更高阶的 3NF 等。通过去除部分依赖,2NF 能减少冗余并提升数据可靠性。尽管会带来一定复杂度,但其在提升数据完整性和简化维护方面的收益,使其成为高效数据库设计的重要组成部分。
如果您准备进一步提升技能,请探索我们的 Database Design 课程,深入理解规范化技术及其实际应用。您也可以通过我们的 SQL Associate Certification 来验证您的 SQL 与数据库管理技能,并向潜在雇主展示您的专业能力!
最后,如果您是企业的决策者,并且意识到需要构建更整洁、更高效的数据库,欢迎提交 DataCamp for Business 演示申请。我们可以帮助提升您团队的能力,以构建可扩展的数据库系统,推动业务效率与创新。我们甚至可以制定定制化学习路径和专属学习轨道。
在处理数据库时,常会遇到数据冗余和更新不一致等问题。第二范式是建立在第一范式(1NF)之上的数据库规范化步骤,用于构建更整洁、更高效的表。
对于从事数据库设计或数据管理的任何人来说,理解 2NF 至关重要,它也为更高阶的规范化形式(如第三范式,3NF)打下基础。本文将通过实际示例介绍 2NF 的工作原理以及如何将表格转换为满足 2NF 要求。我们还会讨论 2NF 的优缺点以及其最适用的场景。
理解第二范式
第二范式是以消除部分依赖为核心的数据库规范化步骤。它由关系型数据库的先驱 Edgar F. Codd 在其规范化研究中提出。
一张表要达到 2NF,必须首先满足第一范式的规则:
在此基础上,2NF 还要求:消除部分依赖。
当某个非主属性(不属于任何候选键的列)仅依赖于复合键的一部分而非整个键时,就发生了部分依赖。2NF 规则确保所有非主属性都依赖于完整的主键,而不是其中某一部分。如果在表中保留部分依赖,冗余数据就可能渗入数据库,导致低效,并在更新或删除时引发潜在不一致。
光讲理论可能有点枯燥,我们来看一个实际例子。
下面是 DataCamp 学生的课程选课表。
这里,主键是学生 ID与课程 ID的复合。然而,非主属性课程名称和课程费用仅依赖于课程 ID,而不是整个键。这违反了 2NF。
分解表以实现 2NF 的步骤
要确保一张表遵循 2NF 的规则,您需要:
第二范式的实践示例
现在我们来看两个示例。
示例 1:课程选课表
前面我们看到如下选课表:
我们按照上一节的步骤来操作。
1. 识别候选键
在该表中,候选键是由学生 ID与课程 ID组成的复合键。这个唯一的组合可以标识表中的每一行。
2. 确定函数依赖
课程名称和讲师姓名依赖于课程 ID,而不是完整的复合键(学生 ID,课程 ID)。这属于部分依赖,因为这些属性只依赖于复合键的一部分。
3. 消除部分依赖
我们需要将只依赖键部分的属性(课程名称和讲师姓名)移动到一个仅基于课程 ID的新表中。
分解后,我们的新表如下:
课程选课表
课程详情表
如果您想亲自动手创建自己的数据库,可以看看我们的 PostgresQL 课程。如果您已有一定基础,可以尝试这门 Introduction to Data Modeling in Snowflake,涵盖实体-关系和维度建模等主题。
示例 2:订单表
我们从这张订单表开始。试着按照上面的步骤自行分解这张表!
1. 识别候选键
订单 ID与产品 ID的组合可以唯一标识每一行,因此(订单 ID,产品 ID)构成一个复合候选键。没有任何单列可以唯一标识行,因为:
这意味着(订单 ID,产品 ID)也是我们的主键。
2. 确定函数依赖
下单日期依赖于订单 ID(而非完整的复合键)。这属于部分依赖。
产品名称和供应商名称依赖于产品 ID(而非完整的复合键)。这些同样是部分依赖。
3. 消除部分依赖
我们需要将该表拆分为更小的表,每个表对应一个逻辑依赖。
首先,我们创建包含订单 ID专属信息的订单信息表。
订单表
接着,我们创建一个包含产品 ID专属信息的表。
订单表
原始表现在仅保留复合键以及订单与产品之间的关联关系。
现在,我们的数据库已满足 2NF,因为 1)所有部分依赖都被消除;2)非主属性完全依赖各自的主键。
何时实施第二范式
那么,为什么要将数据库重构到 2NF?它本身是否足够,还是应该更进一步,目标指向 3NF?
第二范式的优势与局限
第二范式有多项优势,使其成为数据库规范化过程中有用的一步:
但它也有一些局限:
第二范式的性能考量
为消除部分依赖而分解表会直接影响数据库性能。一方面,实现 2NF 可以减少数据冗余并提升一致性,从而在插入、更新或删除操作中更少出现异常。另一方面,规范化会增加表的数量,检索相关数据时需要额外的连接,这可能对大数据集中的查询性能造成影响。
为确保规范化后的数据库仍具备良好性能,请遵循以下最佳实践:
2NF 只是迈向第三范式的过渡步骤吗?
在大多数情况下,数据库设计者会力求达到第三范式,因为它能进一步减少冗余并提升整体数据完整性。然而,实现 3NF 往往需要更多工作,例如创建更多的表和关系,这可能在查询执行中引入复杂性和性能权衡。
也有仅采用第二范式就足够的情况。如果以简洁和快速实施为优先,例如小型项目、原型阶段,或数据冗余极少的情形,2NF 可能已能满足需求。例如,在所有属性都已完全依赖于简单主键的系统中,实现 2NF 就能达成减少部分依赖的主要目标,而无需进一步规范化。
超越第二范式:迈向第三范式
如果您希望进一步规范化数据库,可以继续重构表直至达到第三范式。
3NF 建立在 2NF 之上,解决传递依赖——即非键属性依赖于其他非键属性而不是主键的情况。通过这种推进,确保每个属性都直接依赖于主键而非其他因素。
例如,在跟踪课程选课的表中:
3NF 非常适合对数据完整性和效率有高要求的复杂系统,尤其是在数据量增长时。如果您想深入了解 3NF 及其更严格的形式 BCNF,欢迎阅读我们的文章 What is third normal form?。
结论
第二范式是数据库规范化中的关键一步,承上启下于 1NF 与更高阶的 3NF 等。通过去除部分依赖,2NF 能减少冗余并提升数据可靠性。尽管会带来一定复杂度,但其在提升数据完整性和简化维护方面的收益,使其成为高效数据库设计的重要组成部分。
如果您准备进一步提升技能,请探索我们的 Database Design 课程,深入理解规范化技术及其实际应用。您也可以通过我们的 SQL Associate Certification 来验证您的 SQL 与数据库管理技能,并向潜在雇主展示您的专业能力!
最后,如果您是企业的决策者,并且意识到需要构建更整洁、更高效的数据库,欢迎提交 DataCamp for Business 演示申请。我们可以帮助提升您团队的能力,以构建可扩展的数据库系统,推动业务效率与创新。我们甚至可以制定定制化学习路径和专属学习轨道。