为什么嵌套循环联接仅支持左联接?


11

在Craig Freedman的博客Nested Loops Join中,他解释了为什么嵌套循环联接不能支持正确的外部联接

问题在于,我们多次扫描内部表–对外部联接的每一行扫描一次。在这些多次扫描中,我们可能多次遇到相同的内部行。在什么时候我们可以得出结论,特定的内部行尚未或将不会加入?

有人可以用一种非常简单且具有教育意义的方式来解释这一点吗?

这是否意味着循环从外部表(R1)开始并扫描内部表(R2)?

我了解,对于R1不与相连的值,R2应将其替换为,NULL这样结果集将变为(NULL, R2)。对我来说,似乎无法返回不加入R2时返回值R1,因为它不知道R2要返回哪个值。但这不是它的解释方式。还是?

SQL Server会在事实上优化(经常替换)RIGHT JOINLEFT JOIN,但问题是解释为什么它在技术上是不可能的NESTED LOOPS JOIN使用/支持RIGHT JOIN逻辑。

Answers:


12

这里的主要问题是外执行的加入,使用嵌套循环,在相反的逻辑方式的技术途径,其中,内表是通过访问外环外表通过访问内部循环

给定表A和B,让我们实现A LEFT JOIN B

A
--
1
2

B
_
1
3

首先,让我们以“ 自然 ”的方式进行操作。

我们遍历A。
访问记录1。
我们遍历B。
我们在B中找到记录1,并输出1-1

我们继续遍历A。
访问记录2。
我们遍历B。
我们在B中找不到任何匹配项。
我们输出2-null

现在,让我们以“ 相反 ”的方式进行操作。

我们遍历B。
访问记录1。
我们遍历A。
我们在A中找到记录1,并输出1-1

我们继续遍历B。
我们访问记录3。
我们遍历A。
我们在A中找不到任何匹配项。

现在记住它是A LEFT JOIN B,这意味着除了1-1之外,我们还应该输出2-null
问题在于,在这一点上,我们不知道对于哪些记录id A我们已经有一个匹配项(1),对于哪些记录我们没有(2)。


实际上,可以通过多种方式解决此问题,例如通过为表A保留一个位数组。
当发现A记录为匹配项时,我们在位数组中对其进行标记。
在嵌套循环的末尾,我们将遍历位数组并输出和输出任何未标记的记录。
这显然比“自然的”嵌套循环更复杂。


13

我在链接文章中不喜欢这样的说法:“嵌套循环连接算法不支持右连接的逻辑连接运算符”

尽管存在局限性,但此时的措辞有点令人困惑。我希望以下内容能更好地说明问题:

嵌套垂耳加入算法包括两个表(先前操作的基表或结果集是否是无关的),其被命名为表,并且它们以不同的方式通过算法处理(“外”表在所述外遍历循环和内部循环中的“内部”表)。

因此,可以说我们有一个联接:

A (some_type) JOIN B

该算法可以按以下任一方式执行:

outer-loop-A  nested-loop  inner-loop-B

要么:

outer-loop-B  nested-loop  inner-loop-A

现在,如果(some_type)是INNERor CROSSjoin,则没有限制,计划者可以在两种方式中选择一种(具有不同的性能特征,具体取决于集合的大小,联接列的值分布,索引等)通常,最小的表将被选为算法中的“外部”表)。

但是,当some_typeLEFT加入,它只能使用:

outer-loop-A  nested-loop  inner-loop-B

并不是

outer-loop-B  nested-loop  inner-loop-A

而且,由于RIGHT始终可以将a重写为LEFT联接,因此存在相同的限制。对于A RIGHT JOIN B(可以重写B LEFT JOIN A),它只能使用:

outer-loop-B  nested-loop  inner-loop-A

而不是*

相同的限制适用于左半连接,左反半连接,右半连接和右反半连接。

FULL另一方面,加入不能嵌套循环直接办理加入算法。这篇文章很好地说明了(即将结束)如何将完全联接重写(并由优化程序完成)到左联接和左反半联接的并集,然后可以将其计划为两个嵌套循环(以及一个嵌套循环)。联盟)。

* 正如Dudu Markovitz在他的回答中所解释的那样,将能够使用相反的方式,但前提是我们修改了嵌套循环联接算法,使其最终具有额外的结构和额外的步骤。


好吧,这澄清了很多。您的答案与Dudu M:s相结合,说明得很好!
GordonLiddy
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.