it-swarm.com.de

Wie (und warum) wirkt sich TOP auf einen Ausführungsplan aus?

Bei einer mäßig komplexen Abfrage, die ich optimieren möchte, habe ich festgestellt, dass das Entfernen der Klausel TOP n den Ausführungsplan ändert. Ich hätte vermutet, dass, wenn eine Abfrage TOP n enthält, das Datenbankmodul die Abfrage ausführen würde, wobei die TOP -Klausel ignoriert würde, und am Ende einfach das Ergebnis auf verkleinern würde -n Anzahl der angeforderten Zeilen. Der grafische Ausführungsplan scheint darauf hinzuweisen, dass dies der Fall ist - TOP ist der "letzte" Schritt. Aber es scheint, dass noch mehr los ist.

Meine Frage ist, wie (und warum) wirkt sich eine TOP n-Klausel auf den Ausführungsplan einer Abfrage aus?

Hier ist eine vereinfachte Version dessen, was in meinem Fall vor sich geht:

Die Abfrage stimmt mit Zeilen aus zwei Tabellen überein, A und B.

Ohne die TOP -Klausel schätzt der Optimierer, dass 19.000 Zeilen aus Tabelle A und 46.000 Zeilen aus Tabelle B vorhanden sind. Die tatsächliche Anzahl der zurückgegebenen Zeilen beträgt 16.000 für A und 13.000 für B. Eine Hash-Übereinstimmung wird zum Verbinden verwendet Diese beiden Ergebnismengen für insgesamt 69 Zeilen (dann wird eine Sortierung angewendet). Diese Abfrage erfolgt sehr schnell.

Wenn ich TOP 1001 hinzufüge, verwendet der Optimierer keine Hash-Übereinstimmung. Stattdessen werden zuerst die Ergebnisse aus Tabelle A sortiert (gleiche Schätzung/tatsächliche Schätzung von 19k/16k) und eine verschachtelte Schleife für Tabelle B ausgeführt. Die geschätzte Anzahl der Zeilen für Tabelle B beträgt jetzt 1, und das Seltsame ist, dass TOP n wirkt sich direkt auf die geschätzte Anzahl von Ausführungen (Indexsuche) gegen B aus - es scheint immer 2n + 1 zu sein, oder in meinem Fall 2003. Diese Schätzung ändert sich entsprechend, wenn ich mich ändere TOP n. Da dies ein verschachtelter Join ist, beträgt die tatsächliche Anzahl der Ausführungen natürlich 16 KB (die Anzahl der Zeilen aus Tabelle A), was die Abfrage verlangsamt.

Das eigentliche Szenario ist etwas komplexer, erfasst jedoch die Grundidee/das Grundverhalten. Beide Tabellen werden mit Indexsuchen durchsucht. Dies ist die SQL Server 2008 R2 Enterprise Edition.

35
David

Ich hätte vermutet, dass das Datenbankmodul, wenn eine Abfrage TOP n enthält, die Abfrage ausführen würde, wobei die TOP-Klausel ignoriert wird, und am Ende einfach das Ergebnis auf die Anzahl n Zeilen verkleinern würde das wurde angefordert. Der grafische Ausführungsplan scheint darauf hinzuweisen, dass dies der Fall ist - TOP ist der "letzte" Schritt. Aber es scheint, dass noch mehr los ist.

Die Art und Weise, wie das oben Gesagte formuliert ist, lässt mich denken, dass Sie möglicherweise ein falsches Bild davon haben, wie eine Abfrage ausgeführt wird. Ein Operator in einem Abfrageplan ist kein Schritt (wobei die vollständige Ergebnismenge eines vorherigen Schritts wird vom nächsten ausgewertet.

SQL Server verwendet ein Pipeline-Ausführungsmodell , bei dem jeder Operator Methoden wie Init () , GetRow () und Close () . Wie der Name GetRow () andeutet, erstellt ein Operator bei Bedarf jeweils eine Zeile (wie vom übergeordneten Operator gefordert). Dies ist in den Online-Büchern Referenz zu logischen und physischen Operatoren dokumentiert. Weitere Informationen finden Sie in meinem Blog-Beitrag Warum Abfragepläne rückwärts ausgeführt werden . Dieses zeilenweise Modell ist wichtig, um eine solide Intuition für die Ausführung von Abfragen zu entwickeln.

Meine Frage ist, wie (und warum) wirkt sich eine TOP n-Klausel auf den Ausführungsplan einer Abfrage aus?

Einige logische Operationen wie TOP, Semi-Joins und FAST nAbfragehinweis wirken sich auf die Art und Weise aus, wie der Abfrageoptimierer Ausführungsplanalternativen kostet. Die Grundidee ist, dass eine mögliche Planform die ersten n Zeilen schneller zurückgibt als ein anderer Plan, der für die Rückgabe aller Zeilen optimiert wurde.

Beispielsweise ist die Verknüpfung von indizierten verschachtelten Schleifen häufig der schnellste Weg, um eine kleine Anzahl von Zeilen zurückzugeben, obwohl Hash- oder Zusammenführungsverknüpfungen mit Scans bei größeren Gruppen möglicherweise effizienter sind. Die Art und Weise, wie der Abfrageoptimierer diese Auswahl begründet, besteht darin, an einem bestimmten Punkt im logischen Operationsbaum ein Zeilenziel festzulegen.

Ein Zeilenziel ändert die Art und Weise, wie Abfrageplanalternativen kostenpflichtig sind. Das Wesentliche dabei ist, dass der Optimierer zunächst jeden Operator so kostet, als ob die vollständige Ergebnismenge erforderlich wäre, ein Zeilenziel an der entsprechenden Stelle festlegt und dann den Planbaum zurückarbeitet, um die Anzahl der Zeilen zu schätzen, die er voraussichtlich untersuchen muss das Reihenziel erreichen.

Beispielsweise setzt eine logische TOP(10) an einem bestimmten Punkt im logischen Abfragebaum ein Zeilenziel von 10. Die Kosten der Bediener, die zum Zeilenziel führen, werden geändert, um zu schätzen, wie viele Zeilen sie produzieren müssen, um das Zeilenziel zu erreichen. Diese Berechnung kann komplex werden, daher ist es einfacher, all dies mit einem vollständig ausgearbeiteten Beispiel und kommentierten Ausführungsplänen zu verstehen. Zeilenziele können mehr als die Auswahl des Verknüpfungstyps beeinflussen oder ob Suchvorgänge und Suchvorgänge Scans vorgezogen werden. Weitere Details dazu hier .

Wie immer hängt ein Ausführungsplan, der auf der Grundlage eines Zeilenziels ausgewählt wird, von den Argumentationsfähigkeiten des Optimierers und der Qualität der ihm zur Verfügung gestellten Informationen ab. Nicht jeder Plan mit einem Zeilenziel erzeugt in der Praxis schneller die erforderliche Anzahl von Zeilen, aber gemäß dem Kostenmodell wird dies der Fall sein.

Wenn sich herausstellt, dass ein Zeilenzielplan nicht schneller ist, gibt es normalerweise Möglichkeiten, die Abfrage zu ändern oder dem Optimierer bessere Informationen bereitzustellen, sodass der natürlich ausgewählte Plan am besten ist. Welche Option in Ihrem Fall geeignet ist, hängt natürlich von den Details ab. Die Zeilenzielfunktion ist im Allgemeinen sehr effektiv (obwohl es einen Fehler gibt, auf den Sie achten müssen, wenn Sie in parallelen Ausführungsplänen verwendet werden).

Ihre spezielle Abfrage und Ihr Plan eignen sich möglicherweise nicht für eine detaillierte Analyse (stellen Sie auf jeden Fall einen tatsächlichen Ausführungsplan bereit, wenn Sie dies wünschen), aber hoffentlich können Sie mit den hier beschriebenen Ideen Fortschritte erzielen.

39
Paul White 9

Wenn Sie TOP verwenden, sieht der Optimierer die Möglichkeit, weniger Arbeit zu erledigen. Wenn Sie nach 10 Zeilen fragen, besteht eine gute Chance, dass nicht der gesamte Satz verbraucht werden muss. So kann der TOP-Operator viel weiter nach rechts geschoben werden. Es werden weiterhin Zeilen vom nächsten Operator (rechts) angefordert, bis es genug empfangen hat.

Sie weisen darauf hin, dass die Abfrage ohne TOP die Daten ganz am Ende sortiert. Wenn die Engine im Voraus wissen könnte, wie viele Zeilen durch die Verknüpfung erfüllt werden sollen, kann sie einen ähnlichen Plan verwenden und den TOP links positionieren. Da der Aufwand für ein Hash-Match jedoch relativ hoch ist und vermutlich keine Option für einen Merge-Join besteht, zieht es das Optimierungsprogramm möglicherweise vor, das TOP weiter rechts zu filtern.

Wenn Tabelle B abgefragt wird, wird jeweils eine einzelne Zeile abgerufen. Aus diesem Grund ist die Schätzung 1. Es wird auch davon ausgegangen, dass diese Zeile nur in 50% der Fälle gefunden wird. Es wird also vermutet, dass 2n + 1 benötigt werden, um es zu finden.

12
Rob Farley