Bei dem Versuch, die Geschwindigkeit einer immens langsamen Abfrage zu verbessern (mehrere Minuten in zwei Tabellen mit jeweils nur ~ 50.000 Zeilen, wenn es darauf ankommt, unter SQL Server 2008), habe ich das Problem auf einen OR
in meinem inneren Join eingegrenzt, wie in:
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
Ich habe dies in ein äquivalentes Paar linker Verknüpfungen geändert (was ich hoffe), das hier gezeigt wird:
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
.. und die Abfrage läuft jetzt in ca. einer Sekunde!
Ist es im Allgemeinen eine schlechte Idee, OR
eine Join-Bedingung zu setzen? Oder habe ich einfach Pech beim Layout meiner Tische?
sql
sql-server
sql-server-2008
tsql
inner-join
beladen
quelle
quelle
Antworten:
Diese Art von
JOIN
ist nicht für aHASH JOIN
oder a optimierbarMERGE JOIN
.Es kann als Verkettung von zwei Ergebnismengen ausgedrückt werden:
Da jeder von ihnen ein Equijoin ist, ist
SQL Server
der Optimierer jedoch nicht intelligent genug, um ihn in der von Ihnen geschriebenen Abfrage zu sehen (obwohl sie logisch äquivalent sind).quelle
ON w=x OR y=z
Musters ganz vermeiden sollte .ON w=x OR y=z
? (Danke für Ihre Geduld!)SQL Server
verstehen, dass eine Verkettung erforderlich wäre. Angenommen, die AbfrageSELECT * FROM othertable WHERE parentId = 1 OR id = 2
verwendet eine Verkettung, wenn beide Felder indiziert sind, sodass theoretisch nichts daran hindert, dasselbe in einer Schleife zu tun. ObSQL Server
dieser Plan tatsächlich erstellt wird oder nicht, hängt von sehr vielen Faktoren ab, aber ich habe ihn noch nie im wirklichen Leben gesehen.Ich verwende den folgenden Code, um ein anderes Ergebnis als die für mich funktionierende Bedingung zu erhalten.
quelle
Sie können stattdessen UNION ALL verwenden.
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
quelle
UNION ALL
Sie erhalten Duplikate im Vergleich zu denenJOIN
mit einerOR
Bedingung.union all
was nicht korrekt ist, wie der Artikel, auf den Sie verlinken, ebenfalls beschreibt.