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 FROM
Klauselunterabfragen.
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 Autos
zum Ergebnis der inneren Verbindung Manufacturers
zu 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:
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 FROM
Klauselunterabfragen. 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.