Inner Join mit abgeleiteter Tabelle mit Unterabfrage

8

Umgebung: SQL 2008 R2

Ich habe eine abgeleitete Tabelle mit einer Unterabfrage erstellt und mit der Haupttabelle verknüpft. Ich möchte nur wissen, ob die Unterabfrage nur einmal ausgeführt wird oder für jede Zeile in der Ergebnismenge ausgeführt wird. Betrachten Sie folgendes Beispiel (fiktive Tabellennamen nur als Referenz)

%Vor%

Also wird die für Inner Join verwendete Unterabfrage nur einmal oder mehrmals ausgeführt?

Wenn ich obige Abfrage mit OUTER APPLY neu schreibe, weiß ich sicher, dass die Unterabfrage für jede Zeile ausgeführt wird. Siehe unten.

%Vor%

Ich möchte nur sicherstellen, dass Innerer Join die Unterabfrage nur einmal ausführt.

    
love kumar 21.10.2014, 12:16
quelle

3 Antworten

8

Zunächst ist zu beachten, dass Ihre Abfragen nicht vergleichbar sind, OUTER APPLY muss durch CROSS APPLY oder INNER JOIN durch LEFT JOIN ersetzt werden.

Wenn sie jedoch vergleichbar gemacht werden, können Sie sehen, dass die Abfragepläne für beide Abfragen identisch sind. Ich habe gerade ein Beispiel DDL verspottet:

%Vor%

Ausführen des folgenden:

%Vor%

Gibt den folgenden Plan:

Und zu INNER / CROSS wechseln:

%Vor%

Gibt den folgenden Plan:

Dies sind die Pläne, bei denen keine Daten in den äußeren Tabellen und nur eine Zeile in den Mitarbeitern vorhanden sind, also nicht wirklich realistisch. Im Falle der äußeren Anwendung kann SQL Server feststellen, dass es nur eine Zeile in den Mitarbeitern gibt. Daher wäre es vorteilhaft, nur eine Nested-Loop-Verknüpfung (d. H. Zeilenweise Suche) mit den äußeren Tabellen durchzuführen. Nach dem Einfügen von 1.000 Zeilen in Mitarbeiter ergibt die Verwendung von LEFT JOIN / OUTER APPLY den folgenden Plan:

Sie können hier sehen, dass der Join nun ein Hash-Match-Join ist, was bedeutet, dass SQL Server festgestellt hat, dass es am besten ist, die äußere Abfrage zuerst auszuführen, die Ergebnisse zu hashen und dann von Mitarbeitern zu suchen . Dies bedeutet jedoch nicht, dass die Unterabfrage als Ganzes ausgeführt und die Ergebnisse gespeichert werden. Zur Vereinfachung könnten Sie dies berücksichtigen, aber Prädikate aus der äußeren Abfrage können immer noch verwendet werden, z. B. wenn die Unterabfrage intern ausgeführt und gespeichert wurde , würde die folgende Abfrage massiven Aufwand darstellen:

%Vor%

Was wäre der Sinn, alle Mitarbeiter-Tarife abzurufen, die Ergebnisse zu speichern, nur um einen Mitarbeiter nachzuschlagen? Die Überprüfung des Ausführungsplans zeigt, dass das Prädikat EID = 1 an den Tabellenscan in #AttendanceDetails übergeben wird:

Die Antwort auf die folgenden Punkte lautet also:

  • Wenn ich obige Abfrage mit OUTER APPLY neu schreibe, weiß ich mit Sicherheit, dass die Unterabfrage für jede Zeile ausgeführt wird.
  • Innerer Join führt die Unterabfrage nur einmal aus.

Es kommt darauf an . Die Verwendung von APPLY SQL Server wird versuchen, die Abfrage möglichst als JOIN neu zu schreiben, da dies den optimalen Plan ergibt, sodass die Verwendung von OUTER APPLY nicht garantiert, dass die Abfrage für jede Zeile einmal ausgeführt wird. In ähnlicher Weise garantiert die Verwendung von LEFT JOIN nicht, dass die Abfrage nur einmal ausgeführt wird.

SQL ist eine deklarative Sprache, in der Sie angeben, was Sie tun möchten und nicht wie Sie es tun sollen. Sie sollten sich also nicht auf bestimmte Befehle verlassen, um ein bestimmtes Verhalten auszulösen. Wenn Sie Leistungsprobleme feststellen, überprüfen Sie dies den Ausführungsplan und IO-Statistiken, um herauszufinden, wie es funktioniert, und um herauszufinden, wie Sie Ihre Abfrage verbessern können.

Darüber hinaus matalisiert SQL Server keine Unterabfragen, normalerweise wird die Definition in die Hauptabfrage erweitert, also obwohl Sie Folgendes geschrieben haben:

%Vor%

Was tatsächlich ausgeführt wird, ist eher wie folgt:

%Vor%     
GarethD 21.10.2014, 12:45
quelle
1

Die Unterabfrage wird nur einmal ausgewertet. Um Verwirrung zu vermeiden, könnten wir uns einfach die Unterabfrage als einzelne Tabelle / Ansicht vorstellen, da die äußeren und inneren inneren Abfragen nicht miteinander in Beziehung stehen.

    
anonxen 21.10.2014 12:38
quelle
1

Mit INNER JOIN wird Ihre Sub-Query nur einmal ausgeführt und ihre Datensätze werden intern in tempdb worktable für komplexe Operationen gespeichert und dann mit der ersten Tabelle verbunden.

Mit der APPLY-Klausel wird die Unterabfrage für jede Zeile in der ersten Tabelle ausgeführt.

edit: Verwenden Sie CTE

%Vor%     
Manoj Pandey 21.10.2014 12:39
quelle