散列连接和合并连接(Oracle RDBMS)之间有什么区别?

And*_*nez 57 sql oracle performance join

散列连接和合并连接之间的性能增益/损失是什么,特别是在Oracle RDBMS中?

Dav*_*dge 74

通过根据连接键对要连接的两个数据集进行排序,然后将它们合并在一起来执行"排序合并"连接.合并非常便宜,但排序可能非常昂贵,特别是如果排序溢出到磁盘.如果可以通过索引按排序顺序访问其中一个数据集,则可以降低排序成本,尽管通过索引扫描访问表的大部分块也可能与全表扫描相比非常昂贵.

通过基于连接列将一个数据集散列到存储器中并读取另一个数据集并探测散列表以进行匹配来执行散列连接.当散列表可以完全保存在内存中时,散列连接的成本非常低,总成本远远超过读取数据集的成本.如果哈希表必须以一次通过的方式溢出到磁盘,则成本会上升,而对于多通道排序则会大幅上升.

(在10g之前,从大型表到小型表的外连接在性能方面存在问题,因为优化器无法解决首先访问较小表以进行散列连接的需要,但较大的表首先用于外连接.因此,在这种情况下无法使用散列连接).

通过在连接键上对两个表进行分区,可以降低散列连接的开销.这允许优化器推断来自一个表中的分区的行将仅在另一个表的特定分区中找到匹配,并且对于具有n个分区的表,散列连接被执行为n个独立的散列连接.这具有以下效果:

  1. 每个哈希表的大小都减小了,因此减少了所需的最大内存量,并且可能无需操作来占用临时磁盘空间.
  2. 对于并行查询操作,进程间消息传递的数量大大减少,从而降低了CPU使用率并提高了性能,因为每个散列连接可以由一对PQ进程执行.
  3. 对于非并行查询操作,内存需求减少了n倍,并且先前从查询中投射了第一行.

您应该注意,散列连接只能用于等连接,但合并连接更灵活.

通常,如果您在等连接中加入大量数据,那么散列连接将是更好的选择.

本主题在文档中有很好的介绍.

http://download.oracle.com/docs/cd/B28359_01/server.111/b28274/optimops.htm#i51523

12.1 docs:https://docs.oracle.com/database/121/TGSQL/tgsql_join.htm


Spe*_*nce 7

我只是想编辑这个后代,当我回答这个问题时没有添加oracle的标签.我的回复更适用于MS SQL.

合并连接是最好的,因为它利用了排序,导致一次向下传递以进行连接.如果您有两个表(或覆盖索引),它们的顺序相同,例如主键和该键上的表的索引,那么如果您执行了该操作,则会产生合并连接.

散列连接是次佳的,因为它通常在一个表具有少量(相对)项时完成,它有效地创建了一个临时表,每个行都有哈希值,然后连续搜索以创建连接.

最坏的情况是嵌套循环,它是顺序(n*m),这意味着没有要利用的排序或大小,并且连接只是对于表x中的每一行,搜索表y以进行连接.

  • 如果一个总是比另一个好,那么另一个永远不会被使用,你不觉得吗?我认为差异比这更复杂. (9认同)
  • 嵌套循环并不总是最差的,因为嵌套循环连接非常快地返回它们的第一个结果(低延迟).当你使用提示first_rows时,很可能会使用嵌套循环连接,因为提示表明你想要低延迟.有时用户更喜欢高吞吐量(例如批处理),有时用户更喜欢低延迟(例如在交互式UI中). (7认同)
  • 如果您误解了我,我很抱歉。我试图描述连接的类型以及为什么合并连接是最好的。问题是,合并联接仅在您可以利用排序顺序时才有效,而散列联接仅在联接表中的行数相对较少时才更有效。如果答案中不清楚,我们深表歉意。 (3认同)
  • 开销也有所不同.嵌套循环对小型数据集表现良好,因为没有开销,只需每行成本.散列连接可能具有快速的每行成本,但是存在构建散列表的前期开销. (2认同)