INNER JOIN durumunda "VEYA" sahibi olmak kötü bir fikir mi?


96

Son derece yavaş bir sorgunun hızını artırmaya çalışırken ( her biri yalnızca ~ 50.000 satır olan iki tabloda birkaç dakika , önemliyse SQL Server 2008'de), sorunu aşağıdaki ORgibi iç birleşimimde bir ile daralttım :

SELECT mt.ID, mt.ParentID, ot.MasterID
  FROM dbo.MainTable AS mt
  INNER JOIN dbo.OtherTable AS ot ON ot.ParentID = mt.ID
                                  OR ot.ID = mt.ParentID

Bunu, burada gösterilen eşdeğer bir çift sol birleşim olarak (umduğum şey) değiştirdim:

SELECT mt.ID, mt.ParentID,
   CASE WHEN ot1.MasterID IS NOT NULL THEN
      ot1.MasterID ELSE
      ot2.MasterID END AS MasterID
  FROM dbo.MainTable AS mt
  LEFT JOIN dbo.OtherTable AS ot1 ON ot1.ParentID = mt.ID
  LEFT JOIN dbo.OtherTable AS ot2 ON ot2.ID = mt.ParentID
  WHERE ot1.MasterID IS NOT NULL OR ot2.MasterID IS NOT NULL

.. ve sorgu şimdi yaklaşık bir saniye içinde çalışır!

ORBir birleştirme koşulu koymak genellikle kötü bir fikir mi? Yoksa masalarımın düzeninde bir şekilde şanssız mıyım?


6
Bize sorgunuz yerine yürütme planını gösterin.
Blindy

garip bir ilişki gibi görünüyor
nathan gonzalez

@Blindy: iyi fikir. Yürütme planlarının, Quassnoi'nin aşağıda bahsettiği şeyi gösterdiği ortaya çıktı: ilk sorgu iç içe döngülerle sonuçlanırken, ikincisi hash birleştirme ile yapılır.
yüklü

Yanıtlar:


116

Bu tür, JOINa HASH JOINveya a için optimize edilemez MERGE JOIN.

İki sonuç kümesinin bir araya getirilmesi olarak ifade edilebilir:

SELECT  *
FROM    maintable m
JOIN    othertable o
ON      o.parentId = m.id
UNION
SELECT  *
FROM    maintable m
JOIN    othertable o
ON      o.id = m.parentId

, ancak bunların her biri bir eşittir, ancak, SQL Server'nin optimize edicisi, yazdığınız sorguda görecek kadar akıllı değildir (mantıksal olarak eşdeğer olmalarına rağmen).


3
bu mantıklı, teşekkürler. Hala sorgumla ilgili tuhaf bir şey olup olmadığından emin değilim veya ON w=x OR y=zmodelin birleşiminden tamamen kaçınmalı mıyım?
saat

@ladenedge: Bu birleştirmeler, iç içe bir döngüde bir tablo taraması kullanılarak gerçekleştirilecektir. Masalarınız büyükse bu yavaştır.
Quassnoi

Daha açık olmak gerekirse, "bu birleşimler" dediğinizde, formun tüm birleşimlerini mi kastediyorsunuz ON w=x OR y=z? (Sabrınız için teşekkürler!)
saat

3
@ladenedge: SQL ServerBirleştirmeye ihtiyaç duyulacağını anlamaya yardımcı olabilecek ek koşullar olabilir . Diyelim ki, SELECT * FROM othertable WHERE parentId = 1 OR id = 2her iki alan da dizine alınmışsa sorgu bir birleştirme kullanacaktır , bu nedenle teorik olarak aynı şeyi bir döngüde yapmayı engelleyecek hiçbir şey yoktur. SQL ServerBu planı gerçekten inşa edip etmeyeceğiniz pek çok faktöre bağlıdır, ancak gerçek hayatta inşa edildiğini hiç görmedim.
Quassnoi

Ayrık kümeler olduklarını biliyorsanız, ALL birleşiminin sonuç kümelerini birleştirmekten kaçınarak performansı önemli ölçüde artırabileceğini unutmayın.
Darren Clark

5

Benim için çalışan durumdan farklı sonuç almak için aşağıdaki kodu kullanıyorum.


Select A.column, B.column
FROM TABLE1 A
INNER JOIN
TABLE2 B
ON A.Id = (case when (your condition) then b.Id else (something) END)

-1

Bunun yerine UNION ALL kullanabilirsiniz.

SELECT mt.ID, mt.ParentID, ot.MasterID FROM dbo.MainTable AS mt Union ALL SELECT mt.ID, mt.ParentID, ot.MasterID FROM dbo.OtherTable AS ot


UNION ALLJOINbir ORkoşula kıyasla size kopyaları verecektir .
CodeMonkey

Bunun için UNION haklı olacak. Daha fazla ayrıntı için aşağıdaki bağlantıyı okuyun veya yerine birleştirme
Mitul Panchal

1
evet, ancak örneğinizde union all, bağlantı kurduğunuz makale de açıkladığı gibi doğru olmayan bir şekilde yazdınız .
CodeMonkey
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.