数据库系统 第14节 第1篇 规范化

规范化是数据库设计中的一个重要步骤,它通过消除数据冗余和确保数据依赖性的一致性来提高数据的质量。下面简要介绍从第一范式到第三范式的规范化过程:

  1. 第一范式 (1NF)

    • 消除重复组:确保表中的每一列都是不可分割的基本数据项,每个元组(行)都是唯一的。
    • 表中的每一列都必须是原子的,也就是说不能再被细分为更小的部分。
  2. 第二范式 (2NF)

    • 依赖于主键:除了满足1NF的要求外,所有非主键列都必须完全依赖于整个主键,而不是主键的一部分或任何其他列。
    • 这意味着如果表有复合主键,则非主键列不能只依赖于主键的一部分。
  3. 第三范式 (3NF)

    • 消除非主属性对键的部分和传递依赖:除了满足2NF的要求外,没有非主属性传递依赖于主键。
    • 这意味着如果有一个依赖关系 A → B → C,并且 C 不直接依赖于 A,则需要分解为两个独立的关系以去除传递依赖。

Boyce-Codd 范式 (BCNF)

  • BCNF 是一种比3NF更严格的范式,它要求对于每一个决定因素 X → Y,X 都包含候选键。
  • 这意味着所有依赖关系都是平凡依赖或者由候选键决定的。

规范化的过程可能会导致数据库表数量的增加,这可能会使得查询变得更加复杂,因为可能需要更多的连接操作来获取所需的数据。然而,这种复杂性的增加通常会带来以下好处:

  • 减少数据冗余,从而节省存储空间。
  • 提高数据完整性,减少更新异常。
  • 使得数据库更加易于理解和维护。

在实际应用中,需要根据具体需求权衡是否进行完整的规范化处理,有时为了提高查询性能而牺牲一定的规范化水平也是常见的做法。例如,在某些情况下,可能会使用反规范化技术来优化读取性能,尽管这可能会增加数据冗余和潜在的不一致性。

高级规范化范式

第四范式 (4NF)
  • 第四范式是针对多值依赖进行处理的范式。当一个关系模式 R 中存在 X → Y 的多值依赖,并且 Y 不是 R 的超键的一部分,同时 X 不是 R 的超键时,该模式就不满足 4NF。
  • 为了达到 4NF,需要将多值依赖分离到不同的关系中。
第五范式 (5NF) 或 项目组范式 (Project-Join Normal Form, PJ/NF)
  • 第五范式主要关注的是在经过自然连接和投影操作后得到的结果是否与原始数据相同。
  • 为了满足 5NF,关系模式必须符合 BCNF 并且没有多余的联接依赖。

反规范化

虽然规范化可以带来许多好处,但在某些情况下,为了提高查询性能,可能会选择部分放弃规范化,即进行反规范化。常见的反规范化技术包括:

  • 复制冗余数据:例如,将常用但频繁更改的数据存储在多个相关表中。
  • 创建汇总表:预先计算和存储一些经常需要计算的数据汇总结果。
  • 使用冗余列:例如,存储子项的父项 ID,即使这个信息可以通过关联表获得。

特殊情况

超规范化
  • 超规范化是将数据进一步分解以消除所有函数依赖的一种方法。它试图将数据分解成最小的原子单元,这通常会导致大量的表,可能会使查询变得非常复杂。
逆规范化
  • 逆规范化是指有意地违反规范化规则以提高查询性能。例如,通过存储额外的冗余数据来减少连接操作的需求。

总结

  • 规范化有助于保持数据的一致性和完整性,但可能会增加查询的复杂性。
  • 反规范化则是在特定场景下为了提高性能而采取的策略,可能会增加数据维护的成本。

在实际应用中,通常需要根据具体的应用场景和需求来平衡规范化与反规范化之间的关系。例如,在数据仓库环境中,由于主要关注的是查询性能而非数据插入和更新,因此可能会更多地采用反规范化策略。而在事务处理系统中,数据的完整性和一致性通常更为重要,因此倾向于遵循更高的规范化标准。

我们可以用具体的例子来说明规范化过程中从第一范式到第三范式的转换,以及反规范化的示例。

规范化示例

假设我们有一个关于员工的信息表 Employees,初始状态如下:

EmployeeIDNameDepartmentSupervisorName
1AliceSalesBob
2BobSalesNone
3CarolHRDave
4DaveHRNone
第一范式 (1NF)

这个表已经满足了第一范式的要求,因为每一列都是不可分割的基本数据项,并且每行都有唯一的标识符 EmployeeID

第二范式 (2NF)

接下来检查是否满足第二范式。在这个表中,SupervisorName 列实际上依赖于 DepartmentName 列,而不是仅仅依赖于 EmployeeID。因此,我们需要将其分解,以确保所有非主键列都完全依赖于整个主键 EmployeeID

新的 Employees 表如下:

EmployeeIDNameDepartment
1AliceSales
2BobSales
3CarolHR
4DaveHR

然后,创建一个新的表 Supervisors 来存储员工与其上司之间的关系:

EmployeeIDSupervisorName
1Bob
3Dave

现在,每个表都满足第二范式。

第三范式 (3NF)

在当前的结构中,Supervisors 表中的 SupervisorName 列依赖于 EmployeeID,但是 Employees 表中的 Department 列也依赖于 Name,这构成了传递依赖。为了消除这种传递依赖,我们需要将部门信息提取到单独的表中。

新的 Departments 表如下:

DepartmentIDDepartment
1Sales
2HR

更新 Employees 表以引用 DepartmentID 而不是 Department 名称:

EmployeeIDNameDepartmentID
1Alice1
2Bob1
3Carol2
4Dave2

现在,我们的数据模型满足第三范式。

反规范化示例

假设我们有一个用于报告的数据库,其中包含员工和他们的销售记录。在规范化的情况下,这些数据可能分布在多个表中,如 EmployeesSalesProducts。为了提高报告性能,我们可以创建一个汇总表 SalesSummary,该表包含了员工的姓名、总销售额和部门信息。

规范化后的表可能如下所示:

Employees

EmployeeIDNameDepartmentID
1Alice1
2Bob1

Sales

SaleIDEmployeeIDProductIDQuantitySaleDate
1110152024-07-01
2210222024-07-02

Products

ProductIDProductNamePrice
101Widget A100
102Widget B150

Departments

DepartmentIDDepartment
1Sales

为了提高查询性能,我们可以创建一个反规范化的汇总表 SalesSummary

EmployeeIDNameDepartmentTotalSales
1AliceSales500
2BobSales300

在这个例子中,SalesSummary 表包含了员工姓名、所属部门和总销售额,这些数据原本需要通过多个表连接才能获取。通过这种方式,我们减少了查询时所需的连接操作,从而提高了性能。

总结来说,规范化有助于确保数据的一致性和减少冗余,而反规范化则是为了提高查询性能而有意增加数据冗余的技术。在实际应用中,需要根据具体需求来平衡这两者。

接下来我们将通过具体的例子来说明第四范式 (4NF) 和第五范式 (5NF 或 PJ/NF) 的应用。

第四范式 (4NF)

第四范式主要关注的是消除多值依赖 (MVD)。多值依赖是一种特殊的依赖关系,不同于函数依赖。在多值依赖中,一个集合的值与另一个集合的值相对应,而不是单个值与单个值对应。

示例:多值依赖

假设我们有一个关系模式 Courses,其中包含课程、教师和教材的信息:

CourseIDCourseNameTeacherTextbook
1MathAliceBookA
1MathAliceBookB
2EnglishBobBookC
3PhysicsCarolBookD
3PhysicsCarolBookE

在这个表中,存在多值依赖 CourseID → {Teacher, Textbook}。对于给定的 CourseID,可能存在多个教师和多个教材。这种多值依赖导致了数据冗余和潜在的数据不一致性。

4NF 解决方案

为了达到第四范式,我们需要消除多值依赖。我们可以将 Courses 表分解为两个表:

  1. Courses 表保留课程和教师的信息:

    CourseIDCourseNameTeacher
    1MathAlice
    2EnglishBob
    3PhysicsCarol
  2. Textbooks 表存储课程和教材的信息:

    CourseIDTextbook
    1BookA
    1BookB
    2BookC
    3BookD
    3BookE

这样,我们消除了多值依赖,每个表中的列都只依赖于主键,达到了第四范式的要求。

第五范式 (5NF 或 PJ/NF)

第五范式关注的是联接依赖。在5NF中,我们希望确保通过自然联接和投影操作所得到的结果与原始数据是一致的。

示例:联接依赖

考虑一个包含学生、课程和选课信息的数据库。原始表 Enrollments 包含学生、他们选择的课程以及课程的教师:

StudentIDCourseIDTeacher
11Alice
12Bob
21Alice
23Carol

在这个表中,可能存在联接依赖 StudentID, CourseID → Teacher。这意味着对于给定的学生和课程组合,只能有一个教师。但是,如果我们尝试将此表分解为两个表,可能会引入数据不一致性。

5NF 解决方案

为了达到第五范式,我们需要确保分解后的表能够通过自然联接和投影操作准确地恢复原始数据。

  1. Students 表包含学生信息:

    StudentIDStudentName
    1John
    2Jane
  2. Courses 表包含课程和教师信息:

    CourseIDCourseNameTeacher
    1MathAlice
    2EnglishBob
    3PhysicsCarol
  3. Enrollments 表存储学生和他们选择的课程信息:

    StudentIDCourseID
    11
    12
    21
    23

在这种情况下,通过将原始表分解为三个表,我们确保了可以通过自然联接和投影操作恢复原始数据,因此满足了第五范式的要求。

总结来说,第四范式关注的是消除多值依赖,而第五范式关注的是确保联接依赖不会引入数据不一致性。这两个范式都是为了进一步提高数据的完整性和一致性。

  • 26
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值