12

Ich habe eine komplexe Abfrage, die ich in einer nachfolgenden Abfrage verwenden müssen (eigentlich Aussage aktualisieren). Ich habe versucht, sowohl eine CTE und eine temporäre Tabelle zu verwenden. Die Leistung, die den CTE verwendet, ist schrecklich gegenüber dem Ansatz der temporären Tabelle. Es ist ungefähr 15 Sekunden gegenüber Millisekunden. Um den Test zu vereinfachen, anstatt der CTE/Temp-Tabelle in der nachfolgenden Abfrage beizutreten, habe ich einfach * daraus ausgewählt. In diesem Fall führen sie das gleiche aus.SQL 2005 CTE vs TEMP wenn Tabelle Leistung verwendet in Joins von anderen Tabellen

Ich habe den Ausführungsplan für beide Ansätze sowohl mit den Joins in der nachfolgenden Abfrage untersucht und dann einfach * gewählt. Mit der einfachen Auswahl sind die Abfragepläne ungefähr gleich, aber mit den Joins in der Folge wählen die Abfragepläne nicht aus. Insbesondere der Teil des Abfrageplans zum Erstellen und Auffüllen der temporären Tabelle bleibt derselbe, während sich der Abfrageplanabschnitt zum Erstellen und Auffüllen des CTE erheblich ändert, wenn er anschließend in einer Abfrage mit einem Join verwendet wird.

Meine Frage ist, warum der Abfrageplan für die Erstellung und den Bestand des CTE ändern, wie es später verwendet wird, während die temporäre Tabelle nicht ist. Auch in welchen Szenarien würde ein CTE dann eine bessere Leistung erbringen als eine temporäre Tabelle?

* Anmerkung I als auch eine Tabelle Variable verwendet haben, und es ist auf der temporären Tabelle Ansatz vergleichbar.

Dank

Antwort

9

Sie sind eine komplizierte Frage zu stellen, so dass Sie eine komplizierte Antwort zu bekommen: es hängt davon ab. (Ich hasse diese Antwort).

Im Ernst, jedoch hat es damit zu tun, wie der Optimierer einen Datentarif wählt (die man schon kannte); Eine temporäre Tabelle oder Variable ist wie eine permanente Struktur, da ein Ausführungsplan die Operation ausführt, die dem ersten Füllen dieser Struktur zugeordnet ist, und diese Struktur dann in nachfolgenden Operationen verwendet. Ein CTE ist KEINE temporäre Tabelle. Die Verwendung des CTE wird erst berechnet, wenn er von nachfolgenden Operationen verwendet wird, sodass sich die Verwendung auf die Optimierung des Plans auswirkt.

CTE wurden für Wiederverwertbarkeit und Wartungsprobleme implementiert, die nicht unbedingt die Leistung; In vielen Fällen (wie Rekursion) werden sie jedoch besser funktionieren als herkömmliche Codierungsmethoden.

13

CTE ist nur ein Alias ​​für die Abfrage.

Es kann (oder nicht kann) jedes Mal erneut ausgeführt wird es verwendet wird.

Es gibt keine saubere Art und Weise CTE Materialisierung in SQL Server (wie Oracle /*+ MATERIALIZE */) zu zwingen, und Sie haben wie diese schmutzigen Tricks zu tun:

CTE kann die Leistung verbessern, wenn verwendet, in Plänen, die nur eine Bewertung erfordern (wie HASH JOIN, MERGE JOIN usw.).

In diesen Szenarien wird die Hash-Tabelle direkt aus dem CTE erstellt, während die Verwendung der Temp-Tabelle die CTE auswerten, die Ergebnisse in die temporäre Tabelle ziehen und die temporäre Tabelle erneut lesen muss.

+1

Ja für materialisieren! Ein PK/IX in der Definition könnte nett sein. – crokusek

2

Ich finde, dass in der Regel eine wiederholte CTE keine Leistungsverbesserungen bekommt.

So, zum Beispiel, wenn Sie ein CTE verwenden, um eine Tabelle zu füllen und dann das gleiche CTE zu einer späteren Abfrage beizutreten, kein Vorteil. Leider sind CTEs keine Snapshots und sie müssen buchstäblich wiederholt werden, um in zwei separaten Anweisungen verwendet zu werden, so dass sie tendenziell zweimal ausgewertet werden.

Anstelle von CTEs verwende ich häufig Inline-TVFs (die CTEs enthalten können), die eine ordnungsgemäße Wiederverwendung ermöglichen und nicht besser oder schlechter als CTEs in meinen SPs sind.

Darüber hinaus finde ich, dass der Ausführungsplan schlecht sein kann, wenn der erste Schritt die Statistiken so ändert, dass der Ausführungsplan für den zweiten Schritt immer ungenau ist, weil er vor dem Ausführen von Schritten ausgewertet wird. In diesem Fall sehe ich mir das manuelle Speichern von Zwischenergebnissen an, stelle sicher, dass sie richtig indiziert sind, teile den Prozess in mehrere SPs auf und füge WITH RECOMPILE hinzu, um sicherzustellen, dass spätere SPs Pläne haben, die für die Daten gut sind wird tatsächlich operieren.

0

Ich habe versucht, CTE mit einfach mit Filter von großen Tabelle ausgewählt dann 3 mal unterquerte es.

Danach dasselbe mit temporären Tabellen tun.

Das Ergebnis war 70% zeitaufwendig für CTE -30% zeitaufwendig für Temp-Tabelle. So Temp-Tabelle ist besser für diese Lösungen.

Ich glaube nicht, CTE macht eine temporäre Tabelle nur mit ausgewählten Abfrage, aber 3 mal wählen zu einer großen Tabelle.