非规范化以何种方式提高数据库性能?

我听到很多关于非规范化的内容,这些内容是为了提高某些应用的性能而做出的。 但我从来没有试图做任何有关的事情。

所以,我只是好奇,在规范化数据库中的哪个地方会使性能变差,换句话说,非规范化原则是什么?

如果我需要提高性能,我该如何使用这种技术?

非规范化是一个时空交换。 规范化的数据占用的空间较less,但可能需要连接来构造所需的结果集,因此需要更多的时间。 如果是非规范化的,数据将在几个地方复制。 然后它需要更多的空间,但数据的理想视图是随时可用的。

还有其他的时空优化,例如

  • 非正规化的观点
  • 预先计算的列

与任何这样的方法一样,这提高了读取数据 (因为它们容易获得),但是更新数据变得更加昂贵(因为您需要更新复制或预先计算的数据)。

非规范化通常用于:

  • 避免一定数量的查询
  • 删除一些连接

非规范化的基本思想是,您将添加冗余数据或将其分组,从而能够以更小的成本更轻松地获取这些数据; 这对表演更好。

一个简单的例子?

  • 考虑一个博客的“post”和“评论”表
    • 对于每一篇文章,“评论”表格中都有几行
    • 这意味着要显示相关评论数量的post列表,您必须:
      • 做一个查询来列出post
      • 每个职位做一个查询来计算它有多less评论(是的,这些可以合并为一个,一次获得所有职位的编号)
      • 这意味着几个查询。
  • 现在,如果您在“post”表格中添加“注释数量”字段:
    • 您只需要一个查询来列出post
    • 不需要查询评论表:注释的数量已经被解除标准化到Posts表中。
    • 只有一个返回多个字段的查询比多个查询要好。

现在,有一些成本,是的:

  • 首先,这会在磁盘和内存中花费一些代价,因为您有一些冗余的信息:
    • 评论数量存储在Posts表格中
    • 你也可以在评论表上find这些数字
  • 其次,每次有人添加/删除评论,你必须:
    • 保存/删除评论,当然
    • 而且,更新Posts表中的相应数字。
    • 但是,如果你的博客阅读的人数多于撰写评论的话,那么这可能并不是那么糟糕。

“反常规”这个词导致了devise问题的混乱。 试图通过非规范化来获得高性能数据库就像试图从纽约开车到达目的地。 它不会告诉你要走哪条路。

你需要的是一个好的devise原则,即使devise有时会与规范化的规则相冲突,也会产生一个简单而完善的devise。

一个这样的devise学科是星型模式。 在星型模式中,单个事实表充当表格星形的中心。 其他表称为维度表,它们位于模式的边缘。 尺寸通过看起来像轮子辐条的关系连接到事实表。 星型模式基本上是将多维devise投影到SQL实现上的一种方式。

与星型模式密切相关的是雪花模式,这有点复杂。

如果你有一个好的星型模式,你将能够通过不超过三种连接方式获得数据的各种组合,涉及两个维度和一个事实表。 不仅如此,许多OLAP工具将能够自动破译您的明星devise,并且不需要进一步的编程就可以对您的数据进行点击,深入分析和graphics分析访问。

星型模式devise有时会违反第二和第三范式,但是它为报告和摘录提供了更快的速度和灵活性。 它最常用于数据仓库,数据集市和报告数据库。 从星型模式或其他一些以检索为导向的devise方面来说,你通常会得到更好的结果,而不仅仅是偶然的“非规范化”。

反规范化的关键问题是:

  • 决定要复制哪些数据以及为什么
  • 规划如何保持数据同步
  • 重构查询以使用非规格化字段。

最简单的反规范化types之一就是将一个标识字段填充到表中以避免join。 由于身份不应该改变,这意味着保持数据同步的问题很less出现。 例如,我们将客户端ID填充到多个表中,因为我们经常需要通过客户端查询它们,而不一定需要在查询中表中的客户端表和我们正在查询的表之间的任何数据如果数据完全正常化。 您仍然必须进行一次连接才能获取客户端名称,但是,如果您要查询的表格之外的数据是唯一需要的数据,则要比连接到6个父表格获取客户端名称要好。

然而,除非我们经常在做需要干预桌上的数据的查询,否则没有任何好处。

另一个常见的非规范化可能是将名称字段添加到其他表。 由于名称本质上是可变的,因此您需要确保名称与触发器保持同步。 但是,如果这样可以避免join5个表而不是2个,那么插入或更新的时间可能会稍长一些。

如果您有一定的要求,如报告等,它可以帮助您以各种方式去规范化数据库:

  • 引入某些数据重复来节省自己的一些JOIN(例如,将某些信息填充到一个表中,并确保重复的数据,以便该表中的所有数据并不需要通过连接另一个表来find)

  • 您可以预先计算某些值并将它们存储在表列中,然后每次运行它们以查询数据库。 当然,这些计算的值可能会随着时间的推移而变得“陈旧”,您可能需要在某个时间点重新计算它们,但是读出固定值通常比计算某些东西要便宜(例如,计算子行)

确实有更多的方法来使数据库模式非规范化以提高性能,但是您只需要意识到这样做会让您陷入某种程度的麻烦。 在作出这些决定时,您需要仔细衡量利弊 – 性能优势与您陷入的问题。

考虑一个具有正确的父子关系的数据库。

假设基数是2×1的平均值。

你有两个表,Parent, p行。 2 p行的孩子。

必须读取用于p父行,2xp子行的连接操作手段。 读取的总行数是p + 2x p

考虑将这个反常规化为只有子行的单个表,2x p 。 读取的行数是2 x p

更less的行==更less的物理I / O ==更快。

根据本文的最后一节,

https://technet.microsoft.com/en-us/library/aa224786%28v=sql.80%29.aspx

人们可以使用虚拟非规范化,您可以使用一些非规范化数据创build视图,以便更快速地运行更简单的SQL查询,而底层表保持标准化以实现更快的添加/更新操作(只要您可以定期更新视图比实时)。 我只是自己在关系数据库上课,但是从我一直在读的这个方法来看,这似乎是合乎逻辑的。

去归一化优于归一化的好处

基本上去规范化是用于DBMS而不是用于RDBMS。 正如我们所知,RDBMS与标准化一起工作,这意味着不再重复数据。 但是当你使用外键的时候还是要重复一些数据。

当您使用DBMS时,需要删除规范化。 为此,需要重复。 但是,由于表格之间没有关系,而且每张表格都有不可分割的存在,所以它仍然可以提高性能。