2010-03-05 15 views
25

Wir haben die Abfrage unten. Die Verwendung eines LINKEN OUTER-Joins dauert 9 Sekunden. Wenn Sie LINKE ÄUSSERUNG zu LINKE INNER ändern, wird die Ausführungszeit auf 2 Sekunden reduziert, und die gleiche Anzahl der Zeilen wird zurückgegeben. Da die gleiche Anzahl von Zeilen aus der dbo.Accepts-Tabelle unabhängig vom Join-Typ verarbeitet wird, warum sollte die äußere 3x länger dauern?LEFT INNER JOIN und LEFT OUTER JOIN - Warum dauert der OUTER länger?

SELECT CONVERT(varchar, a.ReadTime, 101) as ReadDate, 
     a.SubID, 
     a.PlantID, 
     a.Unit as UnitID, 
     a.SubAssembly, 
     m.Lot 
    FROM dbo.Accepts a WITH (NOLOCK) 
LEFT OUTER Join dbo.Marker m WITH (NOLOCK) ON m.SubID = a.SubID 
WHERE a.LastModifiedTime BETWEEN @LastModifiedTimeStart AND @LastModifiedTimeEnd 
    AND a.SubAssembly = '400' 
+23

Ich war mir nicht bewusst, dass es so etwas wie eine "LINKE INNER JOIN" gab. Was tut es? –

+5

Ich vermute, dass das 'LEFT' von' LEFT INNER' entfernt wird und es ist nur ein 'INNER JOIN'. –

+1

Mit SQL Server 2005 kann ich keine Abfrage mit 'LINKEN INNEREN JOIN 'ausführen - ich bekomme eine" falsche Syntax nahe dem Schlüsselwort' INNER '"Fehler. Welche Version von SQL Server verwenden Sie? Wenn 2005+, laufen Sie auf einer herabgestuften Kompatibilitätsebene? –

Antwort

35

Die Tatsache, dass die gleiche Anzahl von Zeilen eine nach der Tat zurückgegeben wird, im Voraus die Abfrageoptimierer nicht wissen können, dass jede Zeile in Akzeptiert eine passende Zeile in der Markierung hat, kann sie?

Wenn Sie zwei Tabellen A und B verbinden, sagen Sie A hat 1 Million Zeilen und B hat 1 Zeile. Wenn Sie A LINKER INNERER JOIN B sagen, bedeutet dies, dass nur die Zeilen A und B ergeben können. Der Abfrageplan kann also zuerst B scannen, dann einen Index für einen Bereichsscan in A verwenden und vielleicht 10 zurückgeben Reihen. Aber wenn Sie sagen, ein LINKES ÄUßER BINNEN B dann mindestens alle Zeilen in A zurückgegeben werden müssen, so muss der Plan alles in A scannen, egal was es in B. findetDurch die Verwendung einer OUTER-Verknüpfung eliminieren Sie eine mögliche Optimierung.

Wenn Sie wissen, dass jede Zeile in Accepts eine Übereinstimmung in Marker haben, warum deklarieren Sie dann einen Fremdschlüssel um dies durchzusetzen? Der Optimierer wird die Einschränkung sehen, und wenn sie vertrauenswürdig ist, wird sie im Plan berücksichtigt.

+10

Warten Sie ... Es gibt kein "LINKES INNERES VERBINDEN". Es ist entweder "LINKER JOIN" oder "LINKER OUTER JOIN". "INNER" bedeutet bereits, dass es die Kreuzung ist, und die Kreuzung kann nur eine Sache sein. Deshalb gibt es das Schlüsselwort "OUTER". Nicht sicher, wie diese Antwort 19 Stimmen bekommen hat ... Es sei denn, ich verpasse hier etwas völlig Neues. –

+2

@NicholasPufal: Da SQL-Syntax korrekt ist, hat ['INNER' weder ein' LINKS' noch ein 'RECHTS'] (http://msdn.microsoft.com/en-us/library/ms177634.aspx). "LINKS" oder "LINKS AUS" bedeutet dasselbe, "AUSSEN" ist ein optionales Token. Es gibt viele Kommentare zum OP, die dies bereits abdecken. Aber ich verstehe perfekt, was Randy meint, und ich denke, er hat verstanden, was ich meine. –

+0

Entschuldigung. Ich lese deine Antwort noch einmal und du machst deinen Standpunkt anhand der Worte des Autors. Mein Fehler. Ich habe deine Antwort vorher völlig anders verstanden. –

28

1) in einem Abfragefenster in SQL Server Management Studio, führen Sie den Befehl:

SET SHOWPLAN_ALL ON

2) Ihre langsame Abfrage

3) Ihre Abfrage ausgeführt wird nicht ausgeführt, aber der Ausführungsplan wird zurückgegeben. speichern diese Ausgabe

4) führen Sie Ihre schnelle Version der Abfrage

5) Ihre Abfrage nicht ausgeführt wird, aber der Ausführungsplan zurückgegeben wird. Speichern Sie diesen Ausgang

6) vergleichen Sie die Ausgabe der langsamen Abfrageversion mit der Ausgabe der schnellen Abfrageversion.

7) Wenn du immer noch nicht weißt, warum einer langsamer ist, poste beide Ausgaben in deiner Frage (bearbeite sie) und jemand kann hier von dort aus helfen.

+2

'SET SHOWPLAN_ALL ON' ist mein neuer Lieblingsbefehl für heute !!! –

+2

Ich denke, das ist eher ein "lehre einen Mann zu fischen ..." Antwort. Upvoted für diesen Befehl, den ich alle meine Entwickler zum Lernen zwingen werde. –

+0

Fehlercode: 1193. Unbekannte Systemvariable 'SHOWPLAN_ALL'. Wie ich diesen Befehl ausführen sollte – makkasi

2

Warten - wollte man tatsächlich, dass „die gleiche Anzahl von Zeilen ... verarbeitet werden“ oder dass „die gleiche Anzahl von Zeilen wird zurückgegeben“? Im Allgemeinen würde der äußere Join viel mehr Zeilen verarbeiten, einschließlich derjenigen, für die es keine Übereinstimmung gibt, selbst wenn dieselbe Anzahl an Datensätzen zurückgegeben wird.

+1

Sorry, ich war ein bisschen sorglos. Die gleiche Anzahl von Zeilen wurde zurückgegeben. –

6

Dies liegt daran, dass der LINKE OUTER Join mehr Arbeit macht als ein INNER Join, BEVOR die Ergebnisse zurückgeschickt werden.

Das Innere für alle Datensätze Aussehen verbinden, in dem die ON-Anweisung wahr ist (Also, wenn es eine neue Tabelle erstellt, bringt es nur in Aufzeichnungen, die die m.SubID = a.SubID übereinstimmen). Dann vergleicht es diese Ergebnisse mit Ihrer WHERE-Anweisung (Ihre letzte modifizierte Zeit).

Die linke äußere Verbindung ... Nimmt alle Datensätze in Ihrer ersten Tabelle auf. Wenn die ON-Anweisung nicht wahr ist (m.SubID entspricht nicht einer .SubID), werden NULL die Werte in der Spalte der zweiten Tabelle für dieses Re-Cord-Set einfach NULL.

Der Grund dafür, dass Sie am Ende die gleiche Anzahl von Ergebnissen erhalten, ist wahrscheinlich der Zufall, der aufgrund der WHERE-Klausel nach dem Kopieren der Datensätze auftritt.

Join (SQL) Wikipedia

Verwandte Themen