2013-05-27 3 views
27

Dies ist eine Frage über SQL Server 2008 R2Warum gibt es einen riesigen Performance-Unterschied zwischen temporärer Tabelle und subselect

Ich bin kein DBA, bei weitem. Ich bin ein Java-Entwickler, der von Zeit zu Zeit SQL schreiben muss. (meist in Code eingebettet). Ich möchte wissen, ob ich hier etwas falsch gemacht habe, und wenn ja, was ich tun kann, um zu vermeiden, dass es wieder passiert.

Q1:

SELECT something FROM (SELECT * FROM T1 WHERE condition1) JOIN ... 

Q1 kennzeichnet 14

Q2 verbindet die gleiche wie Q1 ist, mit einer Ausnahme. (SELECT * FROM T1 WHERE condition1) wird zuvor ausgeführt und in einer temporären Tabelle gespeichert.

Dies ist keine korrelierte Unterabfrage.

Q2:

SELECT * INTO #tempTable FROM T1 WHERE condition1 
SELECT something FROM #tempTable JOIN ... 

wieder, 14 verbindet.

Das Ding, das mich jetzt verwirrt, ist, dass Q1> 2min nahm, (versuchte es ein paar Mal, um Zwischenspeicherung zu vermeiden, eine Rolle zu spielen), während Q2 (beide Abfragen kombiniert) 2sec dauerte !!! Was gibt?

+3

Meine Vermutung wäre, dass die geschätzte Anzahl der Zeilen für 'SELECT * FROM T1 WHERE condition1' sehr ungenau ist. Wenn Sie es in eine '# tempTable' materialisieren, bedeutet dies, dass SQL Server genau weiß, wie viele Zeilen zurückgegeben werden. Können Sie die XML-Version beider tatsächlichen Ausführungspläne posten? –

Antwort

40

Warum ist es nicht empfehlenswert, Subqueries zu benutzen?

Datenbankoptimierer (unabhängig davon, welche Datenbank Sie verwenden) kann solche Abfragen (mit Unterabfragen) nicht immer richtig optimieren. In diesem Fall besteht das Problem für den Optimierer darin, die richtige Methode zum Verknüpfen von Ergebnismengen auszuwählen. Es gibt mehrere Algorithmen zum Verknüpfen zweier Ergebnismengen. Die Wahl des Algorithmus hängt von der Anzahl der Datensätze ab, die in der einen und in der anderen Ergebnismenge enthalten sind. Wenn Sie zwei physische Tabellen verknüpfen (Unterabfrage ist keine physische Tabelle), kann die Datenbank die Menge der Daten in zwei Ergebnismengen anhand der verfügbaren Statistiken leicht bestimmen. Wenn eine der Ergebnismengen eine Unterabfrage ist, ist es sehr schwierig zu verstehen, wie viele Datensätze zurückgegeben werden. In diesem Fall kann die Datenbank einen falschen Abfrageplan für den Join auswählen, was zu einer drastischen Reduzierung der Performance der Abfrage führt.

Das Umschreiben der Abfrage mithilfe von temporären Tabellen soll den Datenbankoptimierer vereinfachen. In der neu geschriebenen Abfrage werden alle Ergebnismengen, die an Joins teilnehmen, physikalische Tabellen sein und die Datenbank wird die Länge jedes Ergebnissatzes leicht bestimmen. Dadurch kann die Datenbank den garantiert schnellsten aller möglichen Abfragepläne auswählen. Darüber hinaus wird die Datenbank die richtige Wahl treffen, egal unter welchen Bedingungen. Die umgeschriebene Abfrage mit temporären Tabellen würde auf jeder Datenbank gut funktionieren, dies ist besonders wichtig bei der Entwicklung von portablen Lösungen.Darüber hinaus ist die neu geschriebene Abfrage einfacher zu lesen, einfacher zu verstehen und zu debuggen.

Es versteht sich, dass das Umschreiben der Abfrage mit temporären Tabellen zu einer Verlangsamung aufgrund zusätzlicher Ausgaben führen kann: Erstellen von temporären Tabellen. Wenn die Datenbank nicht mit der Auswahl des Abfrageplans verwechselt wird, führt sie die alte Abfrage schneller als eine neue aus. Diese Verlangsamung wird jedoch immer vernachlässigbar sein. Normalerweise dauert die Erstellung einer temporären Tabelle einige Millisekunden. Das heißt, die Verzögerung kann keinen wesentlichen Einfluss auf die Systemleistung haben und kann normalerweise ignoriert werden.

Wichtig! Vergessen Sie nicht, Indizes für temporäre Tabellen zu erstellen. Die Indexfelder sollten alle Felder enthalten, die in den Join-Bedingungen verwendet werden.

+1

SQL Server-Abfrage-Engine erstellt intern die temporären Tabellen und der oben angegebene Grund ist nicht immer wahr.IT hängt von vielen anderen Faktoren wie Indizes, Fragmentierung, Statistik usw. ab. – AnandPhadke

+2

Indizes für temporäre Tabellen erhöhen die Abfrageleistung. – nirupam

+1

Sie antworten, ist ziemlich irreführend und falsch, Erstellen einer temporären Tabelle sollte nur in bestimmten Fällen in Betracht gezogen werden: http://StackOverflow.com/Questions/42772428/Should-All-Sub-Aquiries-Be-Replaced-with-Montemary-Tables ? noredirect = 1 # comment72660694_42772428 – Arvand

8

Es gibt viele Dinge, die man hier angehen muss, Indizes, Ausführungspläne usw. Das Testen und Vergleichen der Ergebnisse ist der richtige Weg.

Sie könnten die üblichen Verdächtigen, Indizes suchen. Sehen Sie sich den Ausführungsplan an und vergleichen Sie sie. Stellen Sie sicher, dass die WHERE-Klausel die richtigen verwendet. Stellen Sie sicher, dass Sie die Indizes für Ihre JOINs verwenden.

Diese Antworten werden Ihnen sicher viel helfen.

Verwandte Themen