Yuvalanmış döngüler neden yalnızca sol birleşimleri destekler?


11

Craig Freedman'ın Nested Loops Join adlı blogunda, yuvalanmış döngülerin neden sağ dış bir birleşimi destekleyemediğini açıklar:

Sorun, iç tablayı birden çok kez taramamızdır - dış birleşimin her satırı için bir kez. Bu çoklu taramalar sırasında aynı iç sıralarla birçok kez karşılaşabiliriz. Hangi noktada belirli bir iç sıranın katılmadığı veya katılmayacağı sonucuna varabiliriz?

Birisi bunu gerçekten basit ve eğitici bir şekilde açıklayabilir mi?

Döngünün dış tablo ( R1) ile başladığı ve inner ( R2) öğesini taradığı anlamına mı geliyor ?

R1Katılmayan bir değer için sonuç kümesinin ( ) olması için bir değerle R2değiştirilmesi gerektiğini anlıyorum . Benim için katılmadığı zaman bir değer döndürmek imkansız gibi görünüyor , çünkü hangi değerin geri döneceğini bilemiyor . Ama bu şekilde açıklanmadı. Yoksa öyle mi?NULLNULL, R2R2R1R2

SQL Server aslında optimize yapar (ve genellikle yerine geçer) RIGHT JOINile LEFT JOIN, ama soru bu yüzden açıklamaktır teknik bir imkansız NESTED LOOPS JOINkullanmak / destek RIGHT JOINmantığı.

Yanıtlar:


12

Buradaki ana sorun , iç tablonun dış döngüden erişildiği ve dış tablonun iç döngüden erişildiği , mantıksal yolun tersine teknik bir şekilde iç içe halkalar kullanılarak bir dış birleşimin uygulanmasıdır .

Tablo A ve B verildiğinde, uygulayalım A LEFT JOIN B.

A
--
1
2

B
_
1
3

İlk olarak, bunu " doğal " şekilde yapalım .

A ile yineliyoruz.
Rekor 1'e erişiyoruz.
B ile yineliyoruz. B'de
1 kaydı ve 1-1 çıktısını buluyoruz .

A ile yineleme yapmaya devam
ediyoruz. 2. rekor erişiyoruz.
B ile yineleme
yapıyoruz. B'de herhangi bir eşleşme bulamıyoruz . 2-null
çıktı .

Şimdi bunu " zıt " şekilde yapalım .

B. aracılığıyla Biz iterate
Biz rekor 1. erişmek
A. aracılığıyla Biz iterate
Biz A'da rekor 1 bulmak ve çıkış 1-1 .

B ile yinelemeye devam
ediyoruz. Rekor 3'e erişiyoruz.
A ile yineliyoruz. A ile
herhangi bir eşleşme bulamıyoruz.

Şimdi bunun olduğunu hatırlayın A LEFT JOIN B, yani 1-1'e ek olarak 2-null çıktı vermeliyiz .
Sorun şu ki, hangi kayıt kimliği A için zaten bir eşleşmemize (1) ve hangi kayıtlara sahip olmadığımıza dair hiçbir fikrimiz yok (2).


Bu aslında çeşitli şekillerde çözülebilir, örneğin tablo A için bir bit dizisi tutarak. Bir
A kaydı eşleşme olarak bulunduğunda, bunu bit dizisinde işaretleriz.
Yuvalanmış döngülerin sonunda bit dizisine gidiyoruz ve işaretlenmemiş herhangi bir kayıt çıktısı veriyoruz.
Bu "doğal" iç içe döngüden daha karmaşıktır.


13

Ne bağlantılı makalede sevmiyorum "iç içe döngü birleştirme algoritması sağ birleşimin mantıksal birleştirme operatörü desteklemiyor" ifadesidir .

Bir sınırlama olsa da, bu noktada ifade biraz kafa karıştırıcıdır. Umarım aşağıdakiler daha iyi açıklar:

İç içe lop birleştirme algoritması, dış ve tablo olarak adlandırılan ve algoritma tarafından farklı bir şekilde ele alınan ("dış" tablo dıştan çaprazlanır ) iki tablo içerir (temel tablolar veya önceki işlemlerin sonuç kümelerinin alakasız olması). döngü ve iç döngülerdeki "iç" tablo).

Diyelim ki bir katılmamız var:

A (some_type) JOIN B

Algoritma şunlardan biri olarak yürütülebilir:

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

veya:

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

Şimdi, ( some_type) INNERveya CROSSbirleştirilirse, sınırlama yoktur, planlayıcı iki yoldan birini seçebilir (kümelerin boyutuna, birleştirilen sütunların değerlerinin dağılımı, dizinler vb. Genellikle en küçük tablo algoritmada "dış" tablo olarak seçilir).

Ama ne zaman some_typeolduğunu LEFTkatılabilir, sadece kullanabilirsiniz:

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

ve yok

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

Ve a RIGHTher zaman birleştirme olarak yeniden yazılabildiğinden LEFT, tersine aynı sınırlamaya sahiptir. İçin A RIGHT JOIN B(bir yeniden yazılabilir ki B LEFT JOIN A) sadece kullanabilirsiniz:

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

ve tam tersi değil * .

Aynı sınırlama sol-yarı birleşim, sol-anti-yarım birleşim, sağ-yarım birleşim ve sağ-anti-yarım birleşim için de geçerlidir.

FULLDoğrudan iç içe bir döngü ile ele alınamaz diğer taraftan katılmak algoritması katılmak. Makale, tam bir birleştirmenin sol birleşim ve sol anti-semijoin birleşimine nasıl yeniden yazılabileceğini (ve en iyi duruma getirici olduğunu) çok iyi açıklar (daha sonra iki iç içe döngü (ve bir Birlik).

* Dudu Markovitz'in cevabında açıkladığı gibi, bunun tersi kullanılabilir ancak yalnızca iç içe döngü birleştirme algoritmasını ekstra bir yapıya ve sonunda ekstra bir adım olacak şekilde değiştirirsek.


Bu çok açıklığa kavuştu. Cevabınız Dudu M: s ile birleşince çok iyi açıklıyor!
GordonLiddy
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.