it-swarm.com.de

Was ist der Unterschied zwischen einem CTE und einer Temp-Tabelle?

Was ist der Unterschied zwischen einem Common Table Expression (CTE) und einer temporären Tabelle? Und wann sollte ich eins über das andere verwenden?

CTE

WITH cte (Column1, Column2, Column3)
AS
(
    SELECT Column1, Column2, Column3
    FROM SomeTable
)

SELECT * FROM cte

Temp Table

SELECT Column1, Column2, Column3
INTO #tmpTable
FROM SomeTable

SELECT * FROM #tmpTable
179
Rachel

Das ist ziemlich weit gefasst, aber ich werde Ihnen so allgemein wie möglich antworten.

CTEs ...

  • Sind nicht indizierbar (können jedoch vorhandene Indizes für referenzierte Objekte verwenden)
  • Kann keine Einschränkungen haben
  • Sind im Wesentlichen wegwerfbare VIEWs
  • Bleiben Sie nur so lange bestehen, bis die nächste Abfrage ausgeführt wird
  • Kann rekursiv sein
  • Keine dedizierten Statistiken (verlassen Sie sich auf Statistiken zu den zugrunde liegenden Objekten)

# Temp Tables ...

  • Sind echte materialisierte Tabellen, die in tempdb existieren
  • Kann indiziert werden
  • Kann Einschränkungen haben
  • Bleiben Sie für das Leben der aktuellen VERBINDUNG bestehen
  • Kann von anderen Abfragen oder Unterprozeduren referenziert werden
  • Lassen Sie vom Motor dedizierte Statistiken generieren

In Bezug auf den jeweiligen Zeitpunkt gibt es sehr unterschiedliche Anwendungsfälle. Wenn Sie eine sehr große Ergebnismenge haben oder mehr als einmal darauf verweisen müssen, setzen Sie sie in ein #temp Tabelle. Wenn es rekursiv sein muss, verfügbar ist oder nur etwas logisch vereinfachen soll, wird ein CTE bevorzugt.

Außerdem sollte ein CTEniemals für die Leistung verwendet werden. Mit einem CTE werden Sie die Dinge fast nie beschleunigen, da es sich wiederum nur um eine Einwegansicht handelt. Sie können einige nette Dinge mit ihnen machen, aber das Beschleunigen einer Abfrage gehört nicht wirklich dazu.

204
JNK

BEARBEITEN:

Bitte beachten Sie Martins Kommentare unten:

Der CTE wird nicht als Tabelle im Speicher materialisiert. Es ist nur eine Möglichkeit, eine Abfragedefinition zu kapseln. Im Falle des OP wird es inline gesetzt und das gleiche wie bei SELECT Column1, Column2, Column3 FROM SomeTable. Meistens werden sie nicht im Voraus materialisiert, weshalb dies keine Zeilen zurückgibt. WITH T(X) AS (SELECT NEWID())SELECT * FROM T T1 JOIN T T2 ON T1.X=T2.X Überprüfen Sie auch die Ausführungspläne. Obwohl es manchmal möglich ist, den Plan zu hacken, um eine Spule zu bekommen. Es gibt ein Verbindungselement, das einen Hinweis dazu anfordert. - Martin Smith 15. Februar 12 um 17:08 Uhr


Ursprüngliche Antwort

CTE

Lesen Sie mehr über MSDN

Ein CTE erstellt die im Speicher verwendete Tabelle, ist jedoch nur für die darauf folgende spezifische Abfrage gültig. Bei Verwendung der Rekursion kann dies eine effektive Struktur sein.

Möglicherweise möchten Sie auch eine Tabellenvariable verwenden. Dies wird verwendet as Eine temporäre Tabelle wird verwendet und kann mehrmals verwendet werden, ohne dass sie für jeden Join neu materialisiert werden muss. Wenn Sie jetzt einige Datensätze beibehalten müssen, fügen Sie nach der nächsten Auswahl einige weitere Datensätze hinzu, fügen Sie nach einer weiteren Operation einige weitere Datensätze hinzu und geben Sie dann nur diese Handvoll Datensätze zurück. Dies kann eine praktische Struktur sein, da dies nicht der Fall ist muss nach der Ausführung nicht fallen gelassen werden. Meist nur syntaktischer Zucker. Wenn Sie jedoch die Anzahl der Zeilen niedrig halten, wird sie nie auf der Festplatte angezeigt. Weitere Informationen finden Sie unter Was ist der Unterschied zwischen einer temporären Tabelle und einer Tabellenvariablen in SQL Server? .

Temp Tabelle

Lesen Sie mehr über MSDN - Scrollen Sie etwa 40% nach unten

Eine temporäre Tabelle ist buchstäblich eine Tabelle, die auf der Festplatte erstellt wurde und nur in einer bestimmten Datenbank gelöscht werden kann, von der jeder weiß, dass sie gelöscht werden kann. Es liegt in der Verantwortung eines guten Entwicklers, diese Tabellen zu zerstören, wenn sie nicht mehr benötigt werden, aber ein DBA kann sie auch löschen.

Temporäre Tabellen gibt es in zwei Varianten: lokal und global. In Bezug auf MS SQL Server verwenden Sie eine Bezeichnung #tableName Für lokal und eine Bezeichnung ##tableName Für global (beachten Sie die Verwendung eines einfachen oder doppelten # als identifizierendes Merkmal).

Beachten Sie, dass Sie mit temporären Tabellen im Gegensatz zu Tabellenvariablen oder CTE Indizes und dergleichen anwenden können, da dies legitime Tabellen im normalen Sinne des Wortes sind.


Im Allgemeinen würde ich temporäre Tabellen für längere oder größere Abfragen und CTEs oder Tabellenvariablen verwenden, wenn ich bereits einen kleinen Datensatz hätte und einfach schnell ein bisschen Code für etwas Kleines schreiben möchte. Die Erfahrung und der Rat anderer zeigen, dass Sie CTEs verwenden sollten, bei denen eine kleine Anzahl von Zeilen zurückgegeben wird. Wenn Sie eine große Anzahl haben, würden Sie wahrscheinlich von der Möglichkeit profitieren, die temporäre Tabelle zu indizieren.

29
jcolebrand

Das akzeptierte Antwort hier sagt "ein CTE sollte niemals für die Leistung verwendet werden" - aber das könnte irreführen. Im Zusammenhang mit CTEs im Vergleich zu temporären Tabellen habe ich gerade eine Menge Junk aus einer Reihe gespeicherter Prozesse entfernt, da einige Doofus gedacht haben müssen, dass die Verwendung von temporären Tabellen nur wenig oder gar keinen Aufwand bedeutet. Ich habe das Los in CTEs verschoben, mit Ausnahme von , die während des gesamten Prozesses rechtmäßig wiederverwendet werden sollten. Ich habe bei allen Metriken eine Leistung von etwa 20% erzielt. Ich machte mich dann daran, alle Cursor zu entfernen, die versuchten, eine rekursive Verarbeitung zu implementieren. Hier sah ich den größten Gewinn. Am Ende habe ich die Reaktionszeiten um den Faktor zehn verkürzt.

CTEs und temporäre Tabellen haben sehr unterschiedliche Anwendungsfälle. Ich möchte nur betonen, dass das Verständnis und die korrekte Verwendung von CTEs zwar kein Allheilmittel sind, aber zu einigen wirklich herausragenden Verbesserungen sowohl der Codequalität/-wartbarkeit als auch der Geschwindigkeit führen können. Seit ich sie im Griff habe, sehe ich temporäre Tabellen und Cursor als die großen Übel der SQL-Verarbeitung. Mit Tabellenvariablen und CTEs komme ich jetzt für fast alles gut zurecht. Mein Code ist sauberer und schneller.

17
Mel Padden

Ein CTE kann innerhalb einer Abfrage wiederholt aufgerufen werden und wird jedes Mal ausgewertet, wenn auf ihn verwiesen wird. Dieser Prozess kann rekursiv sein. Wenn es nur einmal referenziert wird, verhält es sich ähnlich wie eine Unterabfrage, obwohl CTEs parametrisiert werden können.

Eine temporäre Tabelle bleibt physisch bestehen und kann indiziert werden. In der Praxis kann der Abfrageoptimierer auch Zwischenverknüpfungs- oder Unterabfrageergebnisse hinter den Kulissen beibehalten, z. B. bei Spool-Vorgängen. Daher ist es nicht unbedingt richtig, dass die Ergebnisse von CTEs niemals auf der Festplatte gespeichert werden.

IIRC-Tabellenvariablen (andererseits) sind immer speicherinterne Strukturen.

Die temporäre Tabelle ist ein echtes Objekt in tempdb, aber cte ist nur eine Art Wrapper für komplexe Abfragen, um die Syntax der Organisationsrekursion in einem Schritt zu vereinfachen.

11
Oleg Dok

Der Hauptgrund für die Verwendung von CTEs ist der Zugriff auf Fensterfunktionen wie row_number() und verschiedene andere.

Dies bedeutet, dass Sie Dinge wie die erste oder letzte Zeile pro Gruppe SEHR SEHR schnell und effizient abrufen können - in den meisten praktischen Fällen effizienter als andere Mittel .

with reallyfastcte as (
select *, 
row_number() over (partition by groupingcolumn order by sortingcolumn) as rownum
from sometable
)
select *
from reallyfastcte
where rownum = 1;

Sie können eine ähnliche Abfrage wie oben mit einer korrelierten Unterabfrage oder mit einer Unterabfrage ausführen, aber der CTE ist in fast allen Szenarien schneller.

Darüber hinaus können CTEs wirklich dazu beitragen, Ihren Code zu vereinfachen. Dies kann zu Leistungssteigerungen führen, da Sie die Abfrage besser verstehen und mehr Geschäftslogik einführen können, um das Optimierungsprogramm selektiver zu gestalten.

Darüber hinaus können CTEs die Leistung steigern, wenn Sie Ihre Geschäftslogik verstehen und wissen, welche Teile der Abfrage zuerst ausgeführt werden sollen. Stellen Sie normalerweise Ihre selektivsten Abfragen an die erste Stelle, die zu Ergebnismengen führen, die beim nächsten Join einen Index verwenden können, und fügen Sie die option(force order) hinzu Abfragehinweis

Schließlich verwenden CTEs nicht standardmäßig Tempdb, sodass Sie Konflikte um diesen Engpass durch ihre Verwendung reduzieren.

Temporäre Tabellen sollten verwendet werden, wenn Sie die Daten mehrmals abfragen müssen, oder alternativ, wenn Sie Ihre Abfragen messen und dies durch Einfügen in eine temporäre Tabelle und feststellen Fügen Sie dann einen Index hinzu, mit dem Ihre Leistung verbessert wird.

8
Dave Hilditch

Hier scheint es ein bisschen Negativität gegenüber CTEs zu geben.

Mein Verständnis eines CTE ist, dass es im Grunde eine Art Ad-hoc-Ansicht ist. SQL ist sowohl eine deklarative als auch eine satzbasierte Sprache. CTEs sind eine großartige Möglichkeit, einen Satz zu deklarieren! Es ist eigentlich eine gute Sache, einen CTE nicht indizieren zu können, weil Sie das nicht müssen! Es ist wirklich eine Art syntaktischer Zucker, um das Lesen/Schreiben der Abfrage zu erleichtern. Jeder anständige Optimierer ermittelt den besten Zugriffsplan mithilfe von Indizes für die zugrunde liegenden Tabellen. Dies bedeutet, dass Sie Ihre CTE-Abfrage effektiv beschleunigen können, indem Sie den Indexhinweisen zu den zugrunde liegenden Tabellen folgen.

Nur weil Sie einen Satz als CTE definiert haben, bedeutet dies nicht, dass alle Zeilen im Satz verarbeitet werden müssen. Abhängig von der Abfrage verarbeitet der Optimierer möglicherweise "gerade genug" Zeilen, um die Abfrage zu erfüllen. Vielleicht brauchten Sie nur die ersten 20 oder so für Ihren Bildschirm. Wenn Sie eine temporäre Tabelle erstellt haben, müssen Sie wirklich alle diese Zeilen lesen/schreiben!

Auf dieser Grundlage würde ich sagen, dass CTEs eine großartige Funktion von SQL sind und überall dort verwendet werden können, wo sie die Abfrage leichter lesbar machen. Ich würde nur an eine temporäre Tabelle für einen Batch-Prozess denken, der wirklich jeden einzelnen Datensatz verarbeiten müsste. Selbst dann ist es afaik nicht wirklich zu empfehlen, da es in einer temporären Tabelle für die Datenbank weitaus schwieriger ist, Ihnen beim Zwischenspeichern und bei Indizes zu helfen. Es ist möglicherweise besser, eine permanente Tabelle mit einem PK-Feld zu haben, das für Ihre Transaktion eindeutig ist.

Ich muss zugeben, dass meine Erfahrung hauptsächlich mit DB2 ist, daher gehe ich davon aus, dass CTE in beiden Produkten auf ähnliche Weise funktioniert. Ich werde gerne korrigiert stehen, wenn CTEs in SQL Server irgendwie minderwertig sind. ;)

6
Ben Thurley