数据归一化

标准化数据库的外观以及为什么表结构很重要。

数据规范化是数据库中结构信息的过程,以减少冗余并使数据库更有效。将规范化视为确保您的数据库中每个字段和表都逻辑组织的方法,以便在插入、更新或删除记录时避免数据异常。此过程根据指定规则执行,这些规则规定了表应该如何组织。

规范化是更大数据清洗和标准化过程的一部分,该过程还涉及确认您的数据是准确的、完整的、不包含重复记录,并确保您已为字段选择适当的数据类型。如果您从非规范化表开始,规范化过程将涉及创建额外的、更小的表,这些表可以通过外键相互连接。也许您在单个值更改后必须更新数据库中的相同信息而感到沮丧,或者发现当一条记录被删除时正在丢失宝贵的数据。规范化您的表将帮助解决这两种情况。

本节课中我们将讨论的原则适用于关系数据库管理系统(RDBMS)。如果您使用的是NoSQL或文档型数据库(如MongoDB),以下信息不适用。

简化和减少存储:规范化数据的优势

规范化主要是为了让您的数据更高效,以便您的团队能够找到并使用他们所需的信息。这些优势和规则一旦您熟悉数据库的工作原理,就会显得显而易见,但了解您数据库中每个表和字段的明确目的仍然大有裨益。规范化数据的优势包括:

  • 简化事务查询。在规范化数据中,查询客户地址只需要查看存储这些地址的单个字段。如果您在数据库的不同位置存储了多次客户地址,或者甚至在同一字段中存储了多个地址,那么该查询将需要更长的时间才能执行。

  • 减小数据库的大小。如果您在数据库的多个位置重复存储客户数据,这意味着您为存储该信息预留了多次空间。如果您的数据库只包含几个表,这可能不是一个大问题,但如果是大规模工作,磁盘空间可能会非常宝贵。减少重复信息意味着降低存储成本,无论您是在运行本地服务器还是依赖云托管数据库。

  • 使数据库维护更容易。想想您数据库中多次存储的相同客户数据。每次客户更改地址时,都需要在每个客户地址字段的实例中更新,这留下了许多出错的空间。如果您的数据是规范化的,您将只有一个客户地址字段,它与其他相关表(如订单)相关联。

数据异常

数据异常是信息在数据库中存储的不一致性。当记录更新、添加或删除时,数据库结构的这些缺陷会变得明显。幸运的是,遵守规范化的规则可以防止这些异常发生。

更新异常

更新异常源于数据冗余。例如,假设您的数据库在多个表中的字段中存储客户地址信息。客户更改地址可能会导致这些字段中的一个更新以包含新信息,从而导致数据不一致。

插入异常

当某些字段必须包含数据才能创建记录时,就会发生一个插入异常,而这些数据可能尚未存在。例如,一个非规范化的数据库可能被构建成只有当客户下过订单时才能创建客户账户。规范化该数据库可以通过创建独立的订单客户表来解决此问题,没有规则禁止空值。

删除异常

意外信息丢失是删除异常的结果。例如,假设您的数据库中的某个表包含有关大学课程和选修这些课程的学生信息。如果某个课程因报名人数少而取消,您可能会在删除该课程记录时不小心丢失有价值的学生信息。与插入异常一样,将数据分解成多个具体表可以防止这个问题。

规范化规则

数据规范化的规则首次在20世纪70年代初提出。这些规则被分为称为范式的层级。每一级都是建立在前一级基础之上的——只有当你的数据已经满足第一级的规则时,才能应用第二级规则,依此类推。虽然还有几个比下面列出的三个更多的范式,但前三个对于大多数用例已经足够。

正如我们在数据库简介中所述,数据库中的表应该包含一个实体键,也称为主键。该字段根据唯一ID区分表中的每一行,并在连接表时很有帮助。在进入第一范式之前,你的表需要有实体键字段。

第一范式(1NF)

第一范式(1NF)规定,表中的每个字段只能存储一个值,且你的表不应包含存储相似信息的多个字段,例如标题为地址1地址2的列。

以下是一个我们将根据第一范式进行规范化的表的示例。此表包含有关大学课程及其授课教师的信息。

教授表

教授ID 教授姓名 课程名称
P001 Gene Watson 哲学导论; 伦理学
P002 Melissa King 量子力学
P003 Errol Tyson 宏观经济学
P004 Mary Jacobson 图形小说

我们注意到,虽然我们的字段是不同的,但有一位教授(第一行的Gene Watson)教授两门课程,而且这些信息目前存储在单个单元格中。如果我们根据1NF规范化这个表,我们需要将我们的数据拆分成多个表

规范化教授表

教授ID 教授姓名
P001 Gene Watson
P002 Melissa King
P003 Errol Tyson
P004 Mary Jacobson

规范化课程表

课程ID 课程名称 教授ID
C001 哲学导论 P001
C002 伦理学 P001
C003 量子力学 P002
C004 宏观经济学 P003
C005 图形小说 P004

由于一位教授可以教授多门课程,我们已经将此数据拆分为两个表。现在,我们的Professor表与我们的Course表具有一对多的关系。这种新的表结构满足第一范式,并通过外键,即Professor ID字段将两个表连接起来。

第二范式(2NF)

第二范式关于减少冗余并确保每个字段描述的是关于实体键所标识的内容。为了满足2NF,表中除实体键之外的所有字段必须完全依赖于表的实体键(实体键可能由两个字段组成的复合键)。让我们来看一个新的例子——一个包含有关员工生日信息的表。

员工生日表

员工ID 生日 部门
E001 11月18日 会计
E002 3月29日 销售
E003 6月1日 市场
E004 2月7日 会计

该表满足1NF,因为每一列都是唯一的,并且在每个单元格中只包含一个值。然而,这个表有一个组合键:员工ID + 生日组合构成了表的实体键。该表在当前状态下不符合2NF,因为部门字段只部分依赖于组合键,因为员工的部门不依赖于他们的生日,只依赖于他们的员工ID。为了解决这个问题,我们将这些信息拆分成两个表

标准化员工生日表

员工ID 生日
E001 11月18日
E002 3月29日
E003 6月1日
E004 2月7日

标准化员工部门表

员工ID 部门
E001 会计
E002 销售
E003 市场
E004 会计

第三范式(3NF)

如果一个表满足<强>第三范式(除了满足2NF之外),那么它不包含任何传递依赖。传递依赖发生在列A依赖于列B,而列B又依赖于实体键的情况下。如果你想根据3NF进行规范化,你需要将列A从表中移除,因为它们不直接依赖于实体键,并将其放置在另一个具有自己的实体键的不同表中。

订单表

订单ID 订单日期 客户ID 客户邮编
R001 01/17/2021 C032 99702
R002 03/01/2021 C004 39204
R003 06/30/2021 C054 06505
R004 08/22/2021 C010 84098
R005 09/27/2021 C004 39204

这个表不是第三范式,因为客户邮编字段依赖于客户ID,而这不是本表的实体键(实体键在这里是订单ID)。我们当前的架构可能导致不希望的信息丢失;如果客户C032退货并需要删除此记录,我们会无意中丢失他们的邮编信息。如果客户C004搬家并且他们的邮编发生变化,我们也必须在两个地方更新它,因为他们已经下了多个订单。要将此表转换为3NF——没错——我们将将其拆分成两个表。

标准化订单表

订单ID 订单日期 客户ID
R001 01/17/2021 C032
R002 03/01/2021 C004
R003 06/30/2021 C054
R004 08/22/2021 C010
R005 09/27/2021 C004

标准化客户表

客户ID 客户邮编
C032 99702
C004 39204
C054 06505
C010 84098

规范化的缺点:何时反规范化

一旦达到更高的规范化级别,你的数据库可能在执行某些分析查询时速度较慢——尤其是那些需要获取大量数据的查询。由于规范化数据要求数据库在执行查询时访问多个表,这可能会花费更长的时间,尤其是在数据库复杂性增加的情况下。权衡是规范化数据占用的空间更少。

下一节:数据立方体

从多个维度思考你的数据。

下一篇文章