使用 InfluxDB 进行基础设施监控 | 现场演示
数据库反规范化
什么是数据库反规范化?
数据库反规范化是一种数据库设计过程,旨在实现更快的数据读取。一种方法是在必要时引入冗余数据。
为了进一步解释反规范化的概念,请考虑一个数据库表,该表存储学校的学生记录。每个学生要么不属于任何系,要么最多属于一个系,并且学生从他们所属的系中选修特定数量的课程。为了设计一个反规范化的学生数据库表,您可以添加一个系字段和一个 total_courses 字段。对于未分配到系的学生,系和 total_courses 的值可以为空或为 null。对于分配到一个系的学生,正确的系和 total_courses 将存储在这些字段中。
以下说明了 students 表
student_id | 学生 | 系 | 总课程数 |
---|---|---|---|
43 | Jimmy | 化学 | 5 |
44 | Samuel | ||
45 | Martha | 历史 | 6 |
请注意,Samuel 的系的值为空,因为他没有系。因此,Samuel 的总课程数为 0。
这种数据库设计的主要优点是,您可以使用单个查询检索学生的系及其提供的课程总数。
与上述设计相反,具有规范化设计的表可能有一个单独的 departments 表,其中每一行代表每个学生的系和总课程数。然后,要检索学生的姓名及其系,您需要编写更复杂的查询,使用 JOIN。这将导致读取速度变慢。
反规范化和规范化之间的区别
反规范化与规范化相反。下表并排比较了这些数据库设计过程。
反规范化 | 规范化 |
---|---|
在 SQL 数据库中,反规范化涉及向表中添加更多列,这可能会导致数据重复。 | 规范化提倡创建更多表以减少数据冗余和不一致。 |
写入和更新操作更难,因为可能存在重复数据,并且未能更新特定数据的每个实例都可能导致不一致。 | 在规范化数据库设计中,写入和更新操作更容易。 |
反规范化简化了查询并加快了读取操作。 | 规范化的数据库设计通常需要多个 JOIN 查询来读取数据,这可能会导致性能下降。 |
反规范化是 NoSQL 数据库系统中的常见做法。大多数 NoSQL 数据库将数据存储在文档中而不是关系表中。 | 大多数关系数据库管理系统(或 SQL 数据库)默认都提倡规范化。数据通常存储在多个表中,这些表可以使用主键连接。 |
为什么要反规范化数据?
反规范化数据库的主要原因是为了提高大型数据库的读取速度。此外,反规范化通过减少连接多个表的需要,降低了读取查询的复杂性。
应该反规范化哪些数据?
适合反规范化的数据是来自表中的值,这些值在与另一个表一起工作时经常需要。您可以通过将这种类型的数据复制为当前表中的字段来规范化它。
另一种要反规范化的数据是对大型表中的数据进行计算的结果,例如库存中的项目总数。与每次需要该结果时查询表中的项目并计算所有行相比,将此结果的副本存储为表中的字段可以加快读取操作。
哪些数据不应该反规范化?
尽管反规范化可以提高读取操作的性能,但在某些情况下,反规范化会给数据库设计增加不必要的复杂性。
例如,在存储客户列表及其订购的杂货的数据库中,您不希望通过在客户表中为每个订单添加额外的列来反规范化每个客户的订单。反规范化在这里可能效果不佳,因为客户可能会不定次数地订购杂货,并且表只能有特定数量的列,而无需每次都更改表。下表显示了反规范化 customers 表的尝试
客户 | 订单 1 | 订单 2 | 订单 3 | 订单 4 |
---|---|---|---|---|
Tom | 大米 | 橙汁 | 茶 | 鸡蛋 |
Ola | 豆子 | 面包 |
如果 Tom 下了第五个订单,您需要通过添加一个新列来存储新订单来更改整个 customers 表。对于没有第 5 个订单的其他客户,新列的值也将为空或为 null。除了更改表之外,您可能还需要更新应用程序代码以识别新列。这显然比拥有单独的表(一个用于客户,一个用于他们的订单)更昂贵。
反规范化策略
有很多方法可以设计反规范化表以提高性能。以下是三种策略。
1. 引入重复或冗余数据
这涉及添加一个字段,该字段存储已存储在另一个表中的值,以减少 JOIN 操作的使用并加快读取速度。
以社交媒体应用程序为例,该应用程序具有 users 表和 profile_pictures 表。在页面上显示用户的详细信息和个人资料图片将需要在两个表上执行 JOIN 操作。这种复杂性可以通过反规范化消除。在 users 表中添加一个 profile_picture 字段以保存个人资料图片文件的路径,这将允许使用更简单的查询,该查询的性能应比使用 JOIN 操作更快。
2. 在新字段中存储预先计算的数据
通过在字段中存储计算结果,可以提高数据库的性能。这消除了每次查询数据时都执行计算的需要。例如,在规范化的数据库中,该数据库具有 students 表和另一个 courses 表,计算选修某课程的学生总数的一种方法是使用 WHERE 子句查询 students 表中选修该课程的学生。
但是反规范化通过将选修某课程的学生总数存储为 courses 表中的列来简化任务。因此,单个查询可以找到选修某课程的学生总数,还可以返回有关该课程的其他详细信息。
3. 创建报表生成表
为了在从大型数据库生成报表的系统中获得性能提升,创建存储数据摘要的额外表将比每次需要报表时从实际数据计算更快。
一个很好的例子是存储基于来自 sales 表(具有数千条记录)的数据的每月销售报告的表。可以通过创建另一个名为 monthly_sales 的表来规范化此表,该表将每个月的销售额摘要存储为一行。因此,一行可以代表一个月,例如一月,列可以存储该月销售额。
常见问题解答
1. 为什么要反规范化数据?
数据反规范化加快了读取操作,并减少了查询中复杂的 JOIN 操作。
2. 反规范化的一个例子是什么?
反规范化的一个很好的例子是在表中引入一个额外的字段来复制另一个表中可用的数据。
3. 何时应该反规范化数据?
当读取速度比数据冗余更重要时,反规范化可以使数据库设计受益。换句话说,只要拥有重复数据不会真正破坏事情,并且通过消除额外的 JOIN、减少从多个表中读取数据的需要,使查询更有效率。
要了解有关时序数据库的信息,请查看 InfluxDB。