Ich habe zwei Tische
@T1 TABLE
(
Id INT,
Date DATETIME
)
@T2 TABLE
(
Id INT,
Date DATETIME
)
Diese Tabellen haben einen nicht gruppierten Index für (ID, Datum).
Und ich verbinde diese Tische
SELECT *
FROM T1 AS t1
INNER JOIN T2 AS t2
ON
t1.Id = t2.Id
WHERE
t1.Date <= GETDATE()
AND
t2.Date <= GETDATE()
Dies kann auch als geschrieben werden
SELECT *
FROM T1 AS t1
INNER JOIN T2 AS t2
ON
t1.Id = t2.Id
AND
t1.Date <= GETDATE()
AND
t2.Date <= GETDATE()
Meine Frage ist, welche dieser beiden Abfragen die bessere Leistung liefert und warum? Oder sind sie gleich?
Antworten:
Die Leistung wird gleich sein. Der Optimierer erkennt dies und erstellt denselben Plan.
Andererseits würde ich nicht sagen, dass sie gleich sind. Das erste Formular in der Frage ist weitaus besser lesbar und wird allgemein erwartet.
Für ein Beispiel mit einigen Tabellen, die ich zur Hand habe, können Sie sehen, dass der Ausführungsplan genau der gleiche ist, egal wie ich die Abfrage schreibe.
Sie sollten in der Lage sein, die Abfragepläne für Ihre eigenen Tabellen und Datensätze zu bestimmen, damit Sie sehen können, was in Ihrer Situation passiert.
Gibt diese Ausführungspläne
quelle
INNER JOIN
. Wenn Sie ein werfen,OUTER JOIN
dann sind sie entschieden nicht das selbe.Sie sind semantisch identisch, und der Optimierer sollte keine Probleme haben, diese Tatsache zu erkennen und identische Pläne zu generieren.
Ich neige dazu, Bedingungen, die auf beide Tabellen
ON
verweisen, und Bedingungen, die nur auf eine Tabelle in der Tabelle verweisen, in die Tabelle aufzunehmenWHERE
.Zum
OUTER JOINS
Verschieben können die Bedingungen jedoch die Semantik beeinflussen.quelle
In einfachen Fällen ist es dasselbe. Ich habe jedoch gesehen, dass sehr komplexe Abfragen mit mehreren Joins signifikant unterschiedliche Pläne haben. Bei einer kürzlich von mir bearbeiteten Tabelle wurden fast 6 Millionen Zeilen mit etwa 20 verschiedenen Tabellen verknüpft. Nur die erste Verknüpfung zu dieser Tabelle war eine innere Verknüpfung, alle anderen wurden äußere Verknüpfungen gelassen. Der Filter in der where-Klausel wurde folgendermaßen parametrisiert:
Dieser Filter wurde später im Plan anstelle von früher verwendet. Als ich diese Bedingungen in die erste innere Verknüpfung verschoben habe, hat sich der Plan dramatisch geändert, da der Filter zu Beginn des Plans angewendet wurde, um die Ergebnismenge zu begrenzen, und meine CPU und die verstrichene Zeit um ca. 310% gesunken sind. Wie bei vielen SQL Server-Fragen kommt es also darauf an.
quelle
Im Allgemeinen macht es einen Unterschied, wo Sie die Filter einsetzen.
Während Tom V angibt, dass der Optimierer erkennt, dass die Abfragen identisch sind, und denselben Plan erstellt, ist dies nicht immer der Fall. Dies hängt davon ab, in welcher SQL-Version Sie sich befinden, wie komplex Ihre Abfrage ist und wie wichtig die Abfrage für den gesamten Stapel ist, den das Optimierungsprogramm ermittelt.
Der Optimierer entscheidet möglicherweise, dass dieser Teil des Stapels nicht genügend Zeit kostet, um den besten Plan zu erstellen. Im Allgemeinen erhalten Sie eine bessere Leistung, wenn Sie in der ON-Klausel anstelle der WHERE-Klausel Bedingungen angeben, die die Datenmenge verringern, an der die Abfrage arbeiten muss (sofern möglich, da dies mit einem Outer Join zu einem kartesischen Produkt führt) .)
Es ist für den gelegentlichen SQL-Entwickler etwas einfacher, Filter in der WHERE-Klausel zu erkennen, aber ich habe an einigen großen Tabellen gearbeitet, in denen die Filter in der ON-Klausel die Laufzeit um Stunden verkürzen.
Wenn die Klausel die Anzahl der von der Abfrage gelesenen Zeilen drastisch reduzieren kann, werde ich sie immer in die ON-Klausel einfügen, damit der Optimierer den besseren Plan auswählen kann.
quelle
Unter normalen Umständen können Filterbedingungen entweder in WHERE- oder in JOIN-Klauseln angegeben werden. Ich neige dazu, Filter unter WHERE zu platzieren, es sei denn, die Priorität von OUTER JOIN könnte beeinträchtigt werden (siehe unten) oder der Filter ist sehr spezifisch für diese Tabelle (z. B. TYPE = 12, um eine bestimmte Teilmenge von Zeilen in der Tabelle anzugeben).
Andererseits können sowohl ON- als auch WHERE-Klauseln verwendet werden, um Verknüpfungsbedingungen (im Gegensatz zu Filterbedingungen) anzugeben. Solange Sie nur INNER-Joins verwenden, spielt es keine Rolle, welche Sie unter normalen Umständen verwenden.
Wenn Sie jedoch OUTER-Joins verwenden, kann dies einen großen Unterschied machen. Wenn Sie beispielsweise einen OUTER JOIN zwischen zwei Tabellen (t1 und t2) angeben, dann aber in der WHERE-Klausel eine eqijoin-Beziehung zwischen den Tabellen angeben (z. B. t1.col = t2.col), haben Sie gerade OUTER-Join in INNER-Join konvertiert! Dies liegt daran, dass mit WHERE ein Equijoin (oder möglicherweise sogar ein OUTER-Join, je nach Version mit der veralteten * = -Syntax) ohne Verwendung einer ON-Klausel angegeben werden kann. Wenn WHERE ein inneres Equijoin zwischen Tabellen angibt, überschreibt es ein OUTER JOIN (falls vorhanden).
Die ursprüngliche Frage betraf Filter, bei denen die Art des Joins häufig kein Problem sein sollte, ein Join jedoch auch als Filter fungieren kann. In diesen Situationen kann die Platzierung der Join-Bedingung mit Sicherheit eine Rolle spielen.
quelle
Bei INNER JOINs ist dies ein Stilproblem.
Mit OUTER JOINs wird es jedoch viel interessanter. Sie sollten die Unterschiede zwischen Abfragen mit OUTER JOINs und Bedingungen sowohl in der ON-Klausel als auch in der WHERE-Klausel untersuchen. Die Ergebnismenge ist nicht immer dieselbe. Ist zum Beispiel
das Gleiche wie
quelle