Syntax von INNER JOIN, verschachtelt in OUTER JOIN, im Vergleich zu Abfrageergebnissen


10

TLDR; Wenn Sie sich die beiden Ausführungspläne ansehen, gibt es eine einfache Antwort darauf, welche besser ist? Ich habe absichtlich KEINE Indizes erstellt, damit Sie leichter sehen können, was passiert.

Nach meiner vorherigen Frage, bei der wir Unterschiede in der Abfrageleistung zwischen verschiedenen Join-Stilen (z. B. verschachtelt oder traditionell) festgestellt haben, habe ich festgestellt, dass die verschachtelte Syntax auch das Verhalten der Abfrage ändert. Betrachten Sie die folgenden 2 Abfragen.

SELECT  a.*, m.*, n.*
FROM    dbo.Autos a
LEFT JOIN dbo.Models m
  JOIN dbo.Manufacturers n  -- <-- Nested INNER JOIN
  ON n.ManufacturerID = m.ManufacturerID
ON m.ModelID = a.ModelID

Geben Sie hier die Bildbeschreibung ein

Dies muss nicht dazu führen, dass die Hersteller beitreten, um eine automatische Zeile mit einer ModelID aufzunehmen, die NICHT in der Models-Tabelle enthalten ist.

Geben Sie hier die Bildbeschreibung ein

Unter Verwendung der traditionellen Syntax müssen wir den Join in Manufactures in einen äußeren Join ändern, wie dies der Fall ist. Dies ändert jedoch den Abfrageplan.

SELECT a.*, m.*, n.*
FROM dbo.Autos a
LEFT JOIN dbo.Models m
ON m.ModelID = a.ModelID
LEFT JOIN dbo.Manufacturers n -- <-- Now LEFT OUTER JOIN
ON n.ManufacturerID = m.ManufacturerID

Geben Sie hier die Bildbeschreibung ein

Antworten:


12

Wenn Sie sich die beiden Ausführungspläne ansehen, gibt es eine einfache Antwort darauf, welche besser ist? Ich habe absichtlich KEINE Indizes erstellt, damit Sie leichter sehen können, was passiert.

Der zweite Plan hat niedrigere geschätzte Kosten, daher ist er in diesem begrenzten Sinne „besser“.

Die Datensätze sind so klein, dass der Optimierer nicht viel Zeit damit verbracht hat, nach Alternativen zu suchen. Die erste Form der Abfrage besteht darin, frühzeitig einen Plan mit Hash-Join und einer Tabellenspool zu finden. Die geschätzten Kosten dieses Plans sind so niedrig, dass sich der Optimierer nicht die Mühe macht, nach etwas Besserem zu suchen.

Die zweite Form der Abfrage besteht darin, einen Plan zu finden, der zu Beginn des Suchprozesses nur äußere Verknüpfungen mit verschachtelten Schleifen verwendet, und der Optimierer entscheidet erneut, dass der Plan gut genug ist. Es kommt also vor, dass dieser Plan als billiger eingeschätzt wird.

Das heißt (wie in den Fragenkommentaren erwähnt), dass die beiden Abfragen nicht semantisch identisch sind. Dies ist für Sie möglicherweise nicht wichtig, wenn Sie garantieren können, dass die Ergebnisse für alle möglichen zukünftigen Zustände Ihrer Datenbank immer gleich sind, aber der Optimierer kann diese Annahme nicht treffen. Es werden immer nur Pläne erstellt, die unter allen Umständen garantiert dieselben von SQL angegebenen Ergebnisse liefern.

Ich habe festgestellt, dass die verschachtelte Syntax auch das Verhalten der Abfrage ändert.

Die 'verschachtelte Syntax' ist nur ein Aspekt der gesamten ANSI-Join-Syntaxspezifikation. Um eine vollständige logische Spezifikation für komplexere Verknüpfungsmuster zu aktivieren, erlaubt die Spezifikation (optionale) Klammern und FROMKlauselunterabfragen.

Die Abfrage kann mit derselben ANSI-Syntax in Klammern geschrieben werden:

SELECT
    A.*,
    M.*,
    N.* 
FROM dbo.Autos AS A
LEFT JOIN
(
    dbo.Manufacturers AS N
    JOIN dbo.Models AS M
        ON M.ManufacturerID = N.ManufacturerID
) ON M.ModelID = A.ModelID;

Dieses Formular zeigt deutlich, dass die logische Anforderung darin besteht, die Verbindung von links Autoszum Ergebnis der inneren Verbindung Manufacturerszu verlassen Models. Wenn Sie die optionalen Klammern weglassen, erhalten Sie das Formular, das Sie als "verschachtelt" bezeichnen:

SELECT
    A.*,
    M.*,
    N.* 
FROM dbo.Autos AS A
LEFT JOIN dbo.Manufacturers AS N
JOIN dbo.Models AS M
    ON M.ManufacturerID = N.ManufacturerID
    ON M.ModelID = A.ModelID;

Dies ist keine andere Syntax - es werden lediglich optionale Klammern weggelassen und ein wenig neu formatiert.

Wie Martin erwähnte, ist es auch in diesem Fall möglich, die logische Anforderung mit inneren Verknüpfungen gefolgt von einer rechten äußeren Verknüpfung auszudrücken:

SELECT
    A.*,
    M.*,
    N.* 
FROM dbo.Manufacturers AS N
JOIN dbo.Models AS M
    ON M.ManufacturerID = N.ManufacturerID
RIGHT JOIN dbo.Autos AS A
    ON A.ModelID = M.ModelID;

Alle drei oben genannten Abfrageformulare verwenden dieselbe ANSI-Join-Syntax. Alle drei erstellen zufällig denselben physischen Ausführungsplan mit dem bereitgestellten Datensatz:

Gemeinsamer Ausführungsplan

Wie ich in meiner Antwort auf Ihre vorherige Frage erwähnt habe, führen Abfragen, die genau dieselbe logische Anforderung ausdrücken, nicht immer zu demselben Ausführungsplan. Welches logische Abfrageformular Sie bevorzugen, ist weitgehend eine Frage des Stils. Es gibt im Allgemeinen keine Korrelation zwischen einem bestimmten Stil und "besseren" Abfrageplänen. Ich würde generell davon abraten, eine Abfrage neu zu schreiben, um einen bestimmten Plan zu erhalten, wenn die neue Abfrage nicht wirklich logisch mit der ursprünglichen identisch ist.

Der SQL-Standard erlaubt auch FROMKlauselunterabfragen. Eine weitere Möglichkeit, dieselbe Abfragespezifikation zu schreiben, ist:

SELECT * 
FROM dbo.Autos AS A
LEFT JOIN
(
    SELECT
        N.ManufacturerID,
        ManufacturerName = N.Name,
        M.ModelID,
        ModelName = M.Name
    FROM dbo.Manufacturers AS N
    JOIN dbo.Models AS M
        ON M.ManufacturerID = N.ManufacturerID
) AS R1
    ON R1.ModelID = A.ModelID;

Unter Verwendung der traditionellen Syntax müssen wir den Join in `Manufacturers in einen äußeren Join ändern, wie so ... aber dies ändert den Abfrageplan.

Dies ändert wahrscheinlich die Bedeutung der Abfrage. In diesem Fall handelt es sich technisch gesehen nicht um eine gültige Alternative (siehe jedoch den Kommentar von ypercube zu Ihrer Frage).

Die (optionalen) Klammern in der ANSI-Join-Syntax sind genau für komplexere Join-Anforderungen wie diese vorgesehen. Sie sollten also keine Angst haben, sie bei Bedarf zu verwenden.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.