Was ist der Unterschied zwischen einem Common Table Expression (CTE) und einer temporären Tabelle? Und wann soll ich eins übereinander verwenden?
CTE
WITH cte (Column1, Column2, Column3)
AS
(
SELECT Column1, Column2, Column3
FROM SomeTable
)
SELECT * FROM cte
Temp-Tabelle
SELECT Column1, Column2, Column3
INTO #tmpTable
FROM SomeTable
SELECT * FROM #tmpTable
sql-server
cte
Rachel
quelle
quelle
Antworten:
Das ist ziemlich weit gefasst, aber ich werde Ihnen so allgemein wie möglich antworten.
CTEs ...
VIEW
s#Temp Tables ...
Sie haben sehr unterschiedliche Anwendungsfälle. Wenn Sie eine sehr große Ergebnismenge haben oder mehrmals darauf verweisen müssen, schreiben Sie sie in eine
#temp
Tabelle. Wenn es rekursiv sein muss, wegwerfbar ist oder nur etwas logisch vereinfachen soll,CTE
wird a bevorzugt.Außerdem
CTE
sollte niemals a für die Aufführung verwendet werden . Mit einem CTE werden Sie die Dinge so gut wie 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 ist nicht wirklich eine davon.quelle
BEARBEITEN:
Bitte beachten Sie Martins Kommentare unten:
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 als temporäre Tabelle verwendet und kann mehrmals verwendet werden, ohne dass für jeden Join eine erneute Materialisierung erforderlich ist. Wenn Sie jetzt ein paar Datensätze beibehalten müssen, nach der nächsten Auswahl ein paar weitere Datensätze hinzufügen, nach einer weiteren Operation ein paar weitere Datensätze hinzufügen und dann nur eine Handvoll Datensätze zurückgeben möchten, kann dies eine praktische Struktur sein, wie es nicht der Fall ist muss nach der Ausführung nicht gelöscht werden. Meist nur syntaktischer Zucker. Wenn Sie jedoch die Zeilenanzahl niedrig halten, wird sie niemals auf der Festplatte gespeichert. Siehe Was ist der Unterschied zwischen einer temporären Tabelle und einer Tabellenvariablen in SQL Server? für mehr Details.
Temp-Tabelle
Lesen Sie mehr über MSDN - Scrollen Sie etwa 40% des Weges nach unten
Eine temporäre Tabelle ist im wahrsten Sinne des Wortes 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. Ein DBA kann sie jedoch auch löschen.
Temporäre Tabellen gibt es in zwei Varianten: lokal und global. In Bezug auf MS SQL Server verwenden Sie eine
#tableName
Bezeichnung für lokal und eine##tableName
Bezeichnung 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 im normalen Sinne des Wortes legitime Tabellen 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 wollte. Die Erfahrung und der Rat anderer deuten darauf hin, dass Sie CTEs verwenden sollten, wenn Sie eine geringe Anzahl von Zeilen zurückgegeben haben. Wenn Sie eine große Anzahl haben, würden Sie wahrscheinlich von der Möglichkeit profitieren, die temporäre Tabelle zu indizieren.
quelle
SELECT Column1, Column2, Column3 FROM SomeTable
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.Die akzeptierte Antwort hier lautet: "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, weil einige Doofus gedacht haben müssen, dass die Verwendung temporärer Tabellen nur wenig oder gar keinen Aufwand verursacht. Ich habe das Los in CTEs verschoben, mit Ausnahme derer, die während des gesamten Prozesses legitimerweise wiederverwendet werden sollten. Ich habe nach allen Messwerten etwa 20% an Leistung gewonnen. Ich habe mich dann daran gemacht, alle Cursor zu entfernen, die versucht haben, eine rekursive Verarbeitung zu implementieren. Hier habe ich den größten Gewinn gesehen. Am Ende habe ich die Antwortzeiten um den Faktor zehn verkürzt.
CTEs und Temp-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 in Bezug auf die Codequalität / Wartbarkeit als auch in Bezug auf die Geschwindigkeit führen können. Seit ich sie in den Griff bekommen habe, sehe ich temporäre Tabellen und Cursor als das große Übel der SQL-Verarbeitung. Ich komme jetzt mit Tabellenvariablen und CTEs für fast alles zurecht. Mein Code ist sauberer und schneller.
quelle
Ein CTE kann innerhalb einer Abfrage wiederholt aufgerufen werden und wird jedes Mal ausgewertet, wenn auf ihn verwiesen wird. Dieser Prozess kann rekursiv sein. Wird es nur einmal referenziert, verhält es sich ähnlich wie eine Unterabfrage, obwohl CTEs parametriert werden können.
Eine temporäre Tabelle wird physisch beibehalten und kann indiziert werden. In der Praxis kann es auch vorkommen, dass das Abfrageoptimierungsprogramm die Ergebnisse von Zwischenverknüpfungen oder Unterabfragen hinter den Kulissen beibehält, z.
IIRC-Tabellenvariablen sind dagegen immer speicherinterne Strukturen.
quelle
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.
quelle
Der Hauptgrund für die Verwendung von CTEs ist der Zugriff auf Fensterfunktionen wie
row_number()
und verschiedene andere.Dies bedeutet, dass Sie Dinge tun können, wie die erste oder letzte Reihe pro Gruppe SEHR SEHR schnell und effizient zu erhalten - in den meisten praktischen Fällen effizienter als andere Mittel .
Sie können eine ähnliche Abfrage wie oben mithilfe einer korrelierten Unterabfrage oder mithilfe einer Unterabfrage ausführen, der CTE ist jedoch in fast allen Szenarien schneller.
Darüber hinaus können CTEs dabei helfen, Ihren Code zu vereinfachen. Dies kann zu Leistungsverbesserungen führen, da Sie die Abfrage besser verstehen und mehr Geschäftslogik einführen können, um dem Optimierer zu helfen, selektiver zu sein.
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 in der Regel Ihre selektivsten Abfragen an die erste Stelle, um Ergebnismengen zu erhalten, die beim nächsten Join einen Index verwenden können, und fügen Sie die
option(force order)
Abfrage hinzu HinweisSchließlich verwenden CTEs standardmäßig kein Tempdb, sodass Sie die Konflikte mit diesem Engpass durch deren Verwendung reduzieren.
Temporäre Tabellen sollten verwendet werden, wenn Sie die Daten mehrmals abfragen müssen, oder wenn Sie Ihre Abfragen messen und feststellen, dass durch Einfügen in eine temporäre Tabelle und anschließendes Hinzufügen eines Indexes Ihre Leistung verbessert wird.
quelle
Hier scheint es ein bisschen Negativität gegenüber CTEs zu geben.
Mein Verständnis eines CTE ist, dass es sich im Grunde genommen um eine Art Ad-hoc-Sicht handelt. SQL ist sowohl eine deklarative als auch eine satzbasierte Sprache. CTEs sind eine großartige Möglichkeit, einen Satz zu deklarieren! Einen CTE nicht indizieren zu können, ist eigentlich eine gute Sache, weil Sie es nicht müssen! Es ist wirklich eine Art syntaktischer Zucker, der das Lesen und Schreiben der Abfrage erleichtert. Jeder anständige Optimierer ermittelt den besten Zugriffsplan anhand von Indizes für die zugrunde liegenden Tabellen. Dies bedeutet, dass Sie Ihre CTE-Abfrage effektiv beschleunigen können, indem Sie den Indexhinweisen für die zugrunde liegenden Tabellen folgen.
Nur weil Sie eine Menge als CTE definiert haben, bedeutet dies nicht, dass alle Zeilen in der Menge verarbeitet werden müssen. Abhängig von der Abfrage verarbeitet das Optimierungsprogramm 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!
Aufgrund dessen würde ich sagen, dass CTEs eine großartige Funktion von SQL sind und überall dort verwendet werden können, wo sie die Lesbarkeit der Abfrage verbessern. Ich würde nur über eine temporäre Tabelle für einen Stapelprozess nachdenken, der wirklich jeden einzelnen Datensatz verarbeiten müsste. Selbst dann ist es nicht wirklich empfehlenswert, da es für die Datenbank in einer temporären Tabelle weitaus schwieriger ist, Sie bei der Zwischenspeicherung und den Indizes zu unterstützen. 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 ich hauptsächlich Erfahrung mit DB2 habe. 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. ;)
quelle