ネストされたループ結合が左結合のみをサポートするのはなぜですか?


11

クレイグ・フリードマンのブログ「ネストされたループ結合」では、ネストされたループ結合が右外部結合をサポートできない理由を説明しています。

問題は、内部テーブルを複数回(外部結合の行ごとに1回)スキャンすることです。これらの複数のスキャン中に、同じ内部行に複数回遭遇する可能性があります。特定の内側の行が結合していない、または結合しないと結論できるのはどの時点ですか?

誰かがこれを本当にシンプルで教育的な方法で説明してくれませんか?

それは、ループが外側のテーブル(R1)で始まり、内側のテーブル()をスキャンすることを意味しR2ますか?

R1結合しない値については、結果セットが()になるようにR2aに置き換える必要があることを理解しています。参加しない場合に値を返すことは、私にとって不可能であるように思われます。理由は、返す値がわからないためです。しかし、それはそれが説明される方法ではありません。またはそれは?NULLNULL, R2R2R1R2

SQL Serverは、実際の最適化でない(そして多くの場合、置き換え)RIGHT JOINLEFT JOIN、しかし問題は、それはだ理由を説明することで、技術的には不可能NESTED LOOPS JOINに使用する/サポートRIGHT JOINロジック。

回答:


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

リンクされた記事で私が気に入らないのは、「ネストされたループ結合アルゴリズムは、右結合の論理結合演算子をサポートしていない」という文です。

制限はありますが、この時点での表現は少し混乱します。私は以下がより良く説明することを望みます:

ネストされたLOPは、アルゴリズムは、指定された(以前の操作のベーステーブルまたは結果セットが無関係であるかどうか)は、2つのテーブルを含むジョイン外側及び内側(「外側」テーブルは、外側にトラバースされるテーブル、それらはアルゴリズムによって異なる方法で処理されていますループと内部ループの「内部」テーブル)。

したがって、結合があるとしましょう:

A (some_type) JOIN B

アルゴリズムは次のいずれかとして実行できます。

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

または:

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

現在、(some_type)がINNERor である場合CROSS、制限はありません。プランナーは2つの方法のいずれかを選択できます(セットのサイズ、結合された列の値の分布、インデックスなどに応じて、パフォーマンス特性は異なります)。 。通常、最小のテーブルがアルゴリズムの「外部」テーブルとして選択されます。

ただし、joinの場合some_typeLEFT、次のものしか使用できません。

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

ではなく

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

また、a RIGHTは常にLEFT結合として書き直すことができるため、逆に同じ制限があります。以下のためにA RIGHT JOIN B(書き換えが可能なB LEFT JOIN A)それだけで使用することができます:

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

逆ではありません*

同じ制限が、左セミジョイン、左アンチセミジョイン、右セミジョイン、右アンチセミジョインにも適用されます。

FULL直接ネストされたループで扱うことができない一方、参加アルゴリズムに参加します。この記事では、完全結合を左結合と左反半結合の和集合に(そしてオプティマイザによって)書き換えて、2つの入れ子ループ(および連合)。

* Dudu Markovitzが彼の回答で説明しているように、逆の方法を使用できますが、ネストループ結合アルゴリズムを変更して、最後に追加の構造と追加のステップを追加した場合のみです。


まあ、それはたくさん明らかにしました。Dudu M:sと組み合わせたあなたの答えはそれを非常によく説明しています!
GordonLiddy 2017年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.