何时以及为什么数据库连接费用高昂?

我正在做一些数据库研究,我正在关注关系数据库的一些限制。

我得到的是大桌子的连接是非常昂贵的,但我不完全确定为什么。 DBMS需要做什么来执行连接操作,瓶颈在哪里?
如何反规范化有助于克服这一代价? 其他优化技术(如索引)如何提供帮助?

个人经验值得欢迎! 如果您要发布资源链接,请避开维基百科。 我知道哪里可以find。

与此相关,我想知道像BigTable和SimpleDB这样的云服务数据库使用的非规范化方法。 看到这个问题 。

非规范化以提高性能? 这听起来很有说服力,但它并不能保持水分。

Chris Todd博士与Ted Codd博士一起是关系数据模型的原始支持者,他用耐心的言辞反对规范化,并用科学的方法系统地拆除了他们:他得到了大量的数据库并对这些断言进行了testing

我认为他是在1988-1991年的“ 关系数据库着作”中写下来的,但是这本书后来被编入第八版,并且可能会保留下来,这本书在数据库理论和devise权威性文本“第八版”在未来几十年印刷。 Chris Date是这个领域的专家,当时我们大多数人还在赤脚奔跑。

他发现:

  • 其中一些人举行特殊情况
  • 他们都没有付清一般用途
  • 对于其他特殊情况,他们都显着恶化

这一切都回到了减轻工作集的大小。 包含正确设置的索引的正确select的键的连接是便宜的,并不昂贵,因为在行被实现之前 ,它们允许显着修剪结果。

实现结果涉及批量磁盘读取,这是最昂贵的练习方面的一个数量级。 执行连接,相比之下,逻辑上只需要检索 。 在实践中,甚至没有提取关键值:关键哈希值用于连接比较,减轻了多列连接的成本,从根本上降低了包含string比较的连接的成本。 不仅会更适合caching,还有更less的磁盘读取操作。

而且,一个好的优化器会select最严格的条件,并在执行连接之前应用它,非常有效地利用连接对高基数指数的高select性。

无可否认,这种types的优化也可以应用于非规范化的数据库,但那些希望对规范进行非规范化的人通常在设置索引时不考虑基数。

理解表扫描(在生成连接的过程中检查表中的每一行)在实践中是很less见的。 查询优化器只有在以下一项或多项条件成立时才会select表扫描。

  • 关系中有不到200行(在这种情况下,扫描将会更便宜)
  • 在连接列上没有合适的索引(如果join这些列是有意义的,那么为什么他们没有索引?修复它)
  • 在可以比较列之前需要types强制(WTF?!修复或回家) 查看ADO.NET ISSUE的注释
  • 比较的一个参数是一个expression式(没有索引)

执行操作比不执行操作更为昂贵。 然而,执行错误的操作,被迫进入毫无意义的磁盘I / O,然后在执行连接之前丢弃渣滓,这是非常昂贵的。 即使预先计算了“错误的”操作并合理地使用了指标,仍然存在重大的处罚。 非规范化以预先计算join – 尽pipe需要更新exception – 是对特定join的承诺。 如果你需要不同的参与,那么这个承诺会让你付出巨大的代价。

如果有人想提醒我这是一个不断变化的世界,我想你会发现在较硬的硬件上的较大数据集只是夸大了Date的发现。

对于所有从事计费系统或垃圾邮件发送器工作的人来说(对你不好意思),并且愤怒地设置了手和键盘,告诉我你知道一个事实,即反规范化速度更快,抱歉,但你住在一个特殊的案例 – 具体来说,就是您按顺序处理所有数据的情况。 这不是一般情况,你的策略合理的。

你错误地概括它是没有道理的。 有关在数据仓库场景中适当使用非规范化的更多信息,请参阅注释部分的末尾。

我也想回应

join只是一些lipgloss笛卡尔产品

什么是一个负荷的bollocks。 限制是尽可能早的,首先是限制性的。 你已经读过这个理论,但你还没有明白。 连接被查询优化器视为“谓词适用的笛卡尔产品”。 这是一个符号化表示(实际上是一种标准化),以促进符号分解,所以优化器可以产生所有等价的转换,并按成本和select性对它们进行sorting,从而可以select最佳的查询计划。

要使优化器生成笛卡儿积的唯一方法是不能提供谓词: SELECT * FROM A,B


笔记


David Aldridge提供了一些重要的附加信息。

除了索引和表扫描之外的确有很多其他策略,现代优化器在制定执行计划之前将花费所有的成本。

一个实用的build议:如果它可以被用作外键然后索引它,以便优化器可以使用索引策略。

我曾经比MSSQL优化器更聪明。 之前改变了两个版本。 现在它通常教 。 这是一个非常真实的意义上的专家系统,把许多非常聪明的人的所有智慧都编纂成一个足够封闭的领域,使得基于规则的系统是有效的。


“Bollocks”可能已经不合适了。 我被要求不那么高傲,提醒说math不是谎言。 这是事实,但并不是所有math模型的含义都必须从字面上理解。 负数的平方根是非常方便的,如果你仔细地避免检查他们的荒谬(双关语),并确保你把它们全部取消,然后再试图解释你的等式。

我之所以这么野蛮地回答,是因为这句话是这样说的

join笛卡尔产品…

这可能不是什么意思,但它写的,它是绝对不真实的。 笛卡尔产品是一种关系。 连接是一个function。 更具体地说,连接是关系值函数。 用一个空谓词产生一个笛卡尔积,检查它是否是一个数据库查询引擎的正确性检查,但是没有人在实际中写非约束连接,因为它们在课堂外没有实际价值。

我之所以这么叫,是因为我不希望读者陷入将模型与模型混淆的古代陷阱。 一个模型是一个近似值,为了方便操作而故意简化。


在数据库引擎之间,select表扫描连接策略的截止点可能会有所不同。 它受到树节点填充因子,键值大小和algorithm细节等诸多实现决策的影响,但广义而言,高性能索引的执行时间为k log n + c 。 C语言是一个固定的开销,主要是由build立时间决定的,曲线的形状意味着你没有得到回报(与线性search相比),直到n是几百。


有时非标准化是一个好主意

非规范化是对特定连接策略的承诺。 如前所述,这会干扰其他join策略。 但是,如果您拥有大量磁盘空间,可预测的访问模式以及处理大部分或全部数据的趋势,那么预先计算连接可能是非常值得的。

您还可以计算出您的操作通常使用的访问path,并预先计算这些访问path的所有连接。 这是数据仓库背后的前提,或者至less是由知道自己为什么在做自己的事情的人创build的,而不仅仅是为了符合stream行语。

一个devise合理的数据仓库是通过一个规范化的交易处理系统进行批量转换而定期生成的。 操作和报告数据库的这种分离具有消除OLTP和OLAP(在线事务处理即数据input和在线分析处理即报告)之间的冲突的理想效果。

这里重要的一点是,除了定期更新之外,数据仓库是只读的 。 这提供了更新exception的问题。

不要犯规格化您的OLTP数据库(发生数据input的数据库)的错误。 计费运行可能会更快,但是如果您这样做,则会收到更新exception情况。 曾经试图让读者文摘停止发送你的东西?

现在磁盘空间很便宜,所以请自行解决。 但是非规范化只是数据仓库故事的一部分。 从预先计算的汇总值中可以获得更大的性能收益:每月总计,诸如此类的事情。 总是要减less工作集。


types不匹配的ADO.NET问题

假设您有一个SQL Server表,其中包含varchartypes的索引列,并且您使用AddWithValue传递约束此列上查询的参数。 C#string是Unicode,所以推断的参数types将是NVARCHAR,它与VARCHAR不匹配。

VARCHAR到NVARCHAR是一个扩大的转换,所以它隐式地发生 – 但是告别索引,好运算出原因。


“盘点盘面”(Rick James)

如果一切都caching在内存中, JOINs相当便宜。 也就是说,规范化没有太多的性能损失

如果一个“规范化”的模式导致JOINs打到磁盘很多,但是等效的“非规范化”模式不需要打到磁盘上,那么非规范化就赢得了性能竞争。

来自原作者的评论:现代数据库引擎非常擅长组织访问sorting,以最小化连接操作期间的caching未命中。 上述情况虽然是真实的,但可能会被误解为暗示在大数据上连接必然会造成昂贵的代价。 这会导致缺乏经验的开发人员做出糟糕的决策。

大多数评论者没有注意到的是在复杂的RDBMS中可以使用的广泛的连接方法,而非规范化器总是掩盖了维护非规格化数据的较高成本。 不是每个连接都基于索引,而且数据库有很多优化的algorithm和连接方法,旨在降低join成本。

无论如何,join的成本取决于其types和其他一些因素。 它根本不需要昂贵 – 一些例子。

  • 批量数据是等间距的散列连接确实非常便宜,而且如果散列表不能被caching在内存中,代价才会变得显着。 没有索引需要。 在连接的数据集之间进行等分可能会有很大的帮助。
  • sorting合并连接的成本是由sorting的代价而不是合并来驱动的 – 基于索引的访问方法实际上可以消除sorting的成本。
  • 索引上的嵌套循环连接的成本由b-tree索引的高度和表格块本身的访问所驱动。 这很快,但不适合批量连接。
  • 基于集群的嵌套循环连接要便宜得多,每个连接行需要更less的逻辑IO(如果连接的表都在同一个集群中,那么通过连接的行的连接,连接变得非常便宜)。

数据库被devise成join,而且它们在如何实现它们方面非常灵活,并且通常非常高效,除非它们使连接机制错误。

我认为整个问题是基于一个错误的前提。 join大桌子不一定昂贵。 事实上, 有效地进行连接是关系数据库完全存在的主要原因之一 。 大集合上的连接通常很昂贵,但是很less要将大表A的全部内容与大表B的全部内容连接在一起。而是编写查询,以便使用每个表的重要行 ,由连接保持的实际集合保持较小。

另外,你还有Peter Wone提到的效率,这样只有每个logging的重要部分都需要在内存中,直到最终的结果集被实现。 另外,在有许多连接的大型查询中,您通常希望从较小的表集合开始,然后继续工作,以便保留在内存中的集合尽可能长。

正确完成后,连接通常是比较,组合或过滤大量数据的最佳方式

瓶颈几乎总是磁盘I / O,甚至更具体地说 – 随机磁盘I / O(相比之下,顺序读取速度相当快,可以通过预读策略进行caching)。

join可以增加随机的search – 如果你正在阅读大桌子的小部分。 但是,如果查询优化器认为它会更好,那么查询优化器会将其转换为顺序表扫描(丢弃不需要的行)。

一个非规范化的表有一个类似的问题 – 行很大,在单个数据页上不太适合。 如果你需要远离另一个的行(而且行的大小会使它们分开),那么你将会有更多的随机I / O。 同样,表扫描可能会被迫避免这种情况。 但是,这一次,由于行大,你的表扫描必须读取更多的数据。 除此之外,您将数据从单个位置复制到多个位置,RDBMS具有更多的读取(和caching)function。

有了2个表格,你也可以得到2个聚集索引 – 并且通常可以索引更多(因为更less的插入/更新开销),这可以大大提高性能(主要是因为索引相对较小,快速读取磁盘(或便宜的caching),并减less需要从磁盘读取的表行数量)。

关于连接的唯一开销来自搞清楚匹配的行。 Sql Server使用3种不同types的连接(主要基于数据集的大小)来查找匹配的行。 如果优化器select了错误的连接types(由于统计信息不准确,索引不足,或只是优化器错误或边缘情况),可能会严重影响查询时间。

  • 循环连接对于(至less1个)小数据集来说非常便宜。
  • 合并连接首先需要两种数据集。 但是,如果您join索引列,那么索引已经sorting,不需要做进一步的工作。 否则,在sorting时会有一些CPU和内存的开销。
  • 散列连接需要内存(存储散列表)和CPU(构build散列)。 同样,这对于磁盘I / O来说相当快。 但是 ,如果没有足够的RAM来存储散列表,Sql Server将使用tempdb来存储散列表的一部分和find的行,然后一次只处理散列表的一部分。 与所有东西磁盘一样,这是相当缓慢的。

在最佳情况下,这些不会导致磁盘I / O – 从性能的angular度来看可以忽略不计。

总而言之,在最坏的情况下 – 从x个连接的表读取相同数量的逻辑数据实际上应该更快,因为它是从单个非规格化表中读取的,因为读取的磁盘较小。 要读取相同数量的物理数据,可能会有一些轻微的开销。

由于查询时间通常以I / O成本为主,并且数据大小不会因非规范化而发生变化(减去一些非常小的行开销),所以将表合并在一起并没有太大的好处。 趋于提高性能的非规范化typesIME正在caching计算值,而不是读取计算所需的10,000行。

您join表格的顺序非常重要。 如果您有两组数据,则尝试以某种方式构build查询,以便首先使用最小数据来减less查询必须处理的数据量。

对于某些数据库无关紧要,例如MS SQL在大多数情况下都知道正确的连接顺序。 对于一些(比如IBM Informix)来说,这个顺序完全不同。

当考虑连接的复杂类时,决定是否非规范化或规范化是一个相当简单的过程。 例如,当查询是O(k log n),其中k是相对于期望的输出量值时,我倾向于使用规范化devise我的数据库。

规范化和优化性能的简单方法是考虑如何改变规范化结构,影响非规范化结构。 这可能是有问题的,但是因为它可能需要事务逻辑来处理非规范化的结构化。

由于问题很多,规范化和非规范化的争论不会结束。 自然解决scheme需要两种方法都有很多问题。

作为一般规则,我总是存储一个可以重build的规范化结构和非规范化caching。 最终,这些caching保存我的屁股解决未来的正常化问题。

阐述别人的话,

join只是一些lipgloss笛卡尔产品。 {1,2,3,4} X {1,2,3}会给我们12个组合(nXn = n ^ 2)。 这个计算出的集合作为应用条件的参考。 数据库pipe理系统(DBMS)应用这些条件(比如左右两边都是2或3)来给我们提供匹配条件。 其实它是更优化,但问题是一样的。 对集合大小的改变会使结果大小呈指数增长。 所消耗的内存和CPU周期数量均以指数forms实现。

当我们规范化时,我们完全避免这个计算,想一想书上的每一页都附有一个彩色的粘性。 您可以使用参考推出信息。 我们付出的代价是我们损害了DBMS的本质(数据的最佳组织)