Ich lerne mehr Details in der Tabellenvariablen. Es heißt, dass temporäre Tabellen immer auf der Festplatte sind und sich Tabellenvariablen im Speicher befinden, dh die Leistung der Tabellenvariablen ist besser als die der temporären Tabelle, da die Tabellenvariable weniger E / A-Operationen als die temporäre Tabelle verwendet.
Aber manchmal, wenn eine Tabellenvariable zu viele Datensätze enthält, die nicht im Speicher enthalten sein können, wird die Tabellenvariable wie die temporäre Tabelle auf die Festplatte gelegt.
Aber ich weiß nicht, was die "zu vielen Platten" sind. 100.000 Datensätze? oder 1000.000 Datensätze? Wie kann ich feststellen, ob sich eine von mir verwendete Tabellenvariable im Speicher oder auf der Festplatte befindet? Gibt es in SQL Server 2005 eine Funktion oder ein Tool, mit dem Sie die Skalierung der Tabellenvariablen messen oder wissen lassen können, wann die Tabellenvariable aus dem Speicher auf die Festplatte gestellt wird?
tempDB
- das "im Speicher" ist ein Mythos. Außerdem: Tabellenvariablen werden vom Abfrageoptimierer immer so betrachtet, dass sie genau eine Zeile enthalten. Wenn Sie viel mehr haben, kann dies zu ernsthaft schlechten Ausführungsplänen führen.tempdb
(aber kann auch ganz in Erinnerung bleiben)Antworten:
Ihre Frage zeigt, dass Sie einigen der häufigsten Missverständnisse in Bezug auf Tabellenvariablen und temporäre Tabellen erlegen sind.
Ich habe auf der DBA-Site eine ziemlich ausführliche Antwort geschrieben, die sich mit den Unterschieden zwischen den beiden Objekttypen befasst. Hiermit wird auch Ihre Frage zu Festplatte und Speicher beantwortet (ich habe keinen signifikanten Unterschied im Verhalten zwischen den beiden festgestellt).
In Bezug auf die Frage im Titel, wann eine Tabellenvariable im Vergleich zu einer lokalen temporären Tabelle verwendet werden soll, haben Sie nicht immer die Wahl. In Funktionen ist es beispielsweise nur möglich, eine Tabellenvariable zu verwenden. Wenn Sie in einem untergeordneten Bereich in die Tabelle schreiben müssen, reicht nur eine
#temp
Tabelle aus (tabellenwertige Parameter ermöglichen schreibgeschützten Zugriff ).Wenn Sie die Wahl haben, finden Sie unten einige Vorschläge (obwohl die zuverlässigste Methode darin besteht, beide einfach mit Ihrer spezifischen Arbeitslast zu testen).
Wenn Sie einen Index benötigen, der nicht für eine Tabellenvariable erstellt werden kann, benötigen Sie natürlich eine
#temporary
Tabelle. Die Details hierzu sind jedoch versionabhängig. Für SQL Server 2012 und darunter waren die einzigen Indizes, die für Tabellenvariablen erstellt werden konnten, diejenigen, die implizit durch eineUNIQUE
oderPRIMARY KEY
-Einschränkung erstellt wurden. In SQL Server 2014 wurde die Inline-Indexsyntax für eine Teilmenge der in verfügbaren Optionen eingeführtCREATE INDEX
. Dies wurde seitdem erweitert, um gefilterte Indexbedingungen zu ermöglichen. Indizes mitINCLUDE
-d Spalten oder Columnstore-Indizes können jedoch immer noch nicht für Tabellenvariablen erstellt werden.Wenn Sie wiederholt eine große Anzahl von Zeilen zur Tabelle hinzufügen und daraus löschen, verwenden Sie eine
#temporary
Tabelle. Dies unterstütztTRUNCATE
(was effizienter ist alsDELETE
bei großen Tabellen) und zusätzlich nachfolgende Einfügungen nach aTRUNCATE
können eine bessere Leistung haben als solche nach a,DELETE
wie hier dargestellt .#temporary
Tabelle. Dies unterstützt die Erstellung von Statistiken, mit denen der Plan dynamisch gemäß den Daten neu kompiliert werden kann (obwohl für zwischengespeicherte temporäre Tabellen in gespeicherten Prozeduren das Neukompilierungsverhalten separat verstanden werden muss).SELECT
Anweisung stammt, sollten Sie berücksichtigen, dass die Verwendung einer Tabellenvariablen die Möglichkeit der Verwendung eines parallelen Plans blockiert.#temp
Tabelle innerhalb eines Benutzers können Transaktionssperren länger gehalten werden als für Tabellenvariablen (möglicherweise bis zum Ende der Transaktion im Vergleich zum Ende der Anweisung, abhängig von der Art der Sperre und der Isolationsstufe) und das Abschneiden destempdb
Transaktionsprotokolls bis zum Benutzertransaktion endet. Dies könnte also die Verwendung von Tabellenvariablen begünstigen.#temporary
Tabellen. Bob Ward weist in seinertempdb
Präsentation darauf hin, dass dies unter Bedingungen hoher Parallelität zu zusätzlichen Konflikten bei Systemtabellen führen kann. Darüber hinaus kann dies beim Umgang mit kleinen Datenmengen einen messbaren Unterschied zur Leistung bewirken .Auswirkungen der Rowset-Freigabe
quelle
id
und der Verwendung vonOPTION (RECOMPILE)
wäre wahrscheinlich in Ordnung - aber testen Sie beide.Verwenden Sie eine Tabellenvariable, wenn für eine sehr kleine Datenmenge (Tausende von Bytes)
Verwenden Sie eine temporäre Tabelle für viele Daten
Eine andere Möglichkeit, darüber nachzudenken: Wenn Sie der Meinung sind, dass Sie von einem Index, automatisierten Statistiken oder einer SQL-Optimierungsfunktion profitieren könnten, ist Ihr Datensatz wahrscheinlich zu groß für eine Tabellenvariable.
In meinem Beispiel wollte ich nur ungefähr 20 Zeilen in ein Format einfügen und sie als Gruppe ändern, bevor ich sie zum UPDATE / INSERT einer permanenten Tabelle verwendete. Eine Tabellenvariable ist also perfekt.
Ich führe aber auch SQL aus, um Tausende von Zeilen gleichzeitig zu füllen, und ich kann definitiv sagen, dass die temporären Tabellen eine viel bessere Leistung als Tabellenvariablen aufweisen.
Dies ist nicht unähnlich, wie CTEs aus einem ähnlichen Grund ein Problem darstellen. Wenn die Daten im CTE sehr klein sind, finde ich, dass ein CTE genauso gut oder besser abschneidet als das, was der Optimierer vorschlägt, aber wenn er dann ziemlich groß ist es tut dir weh
Mein Verständnis basiert hauptsächlich auf http://www.developerfusion.com/article/84397/table-variables-v-temporary-tables-in-sql-server/ , das viel detaillierter ist.
quelle
Microsoft sagt hier
quelle
Ich stimme Abacus voll und ganz zu (sorry - ich habe nicht genug Punkte, um einen Kommentar abzugeben).
Denken Sie auch daran, dass es nicht unbedingt darauf ankommt, wie viele Datensätze Sie haben, sondern auf die Größe Ihrer Datensätze.
Haben Sie beispielsweise den Leistungsunterschied zwischen 1.000 Datensätzen mit jeweils 50 Spalten und 100.000 Datensätzen mit jeweils nur 5 Spalten berücksichtigt?
Schließlich fragen Sie vielleicht mehr Daten ab, als Sie benötigen? Hier finden Sie eine gute Lektüre zu SQL-Optimierungsstrategien . Begrenzen Sie die Datenmenge, die Sie abrufen, insbesondere wenn Sie nicht alles verwenden (einige SQL-Programmierer werden faul und wählen einfach alles aus, obwohl sie nur eine winzige Teilmenge verwenden). Vergessen Sie nicht, dass der SQL Query Analyzer möglicherweise auch Ihr bester Freund wird.
quelle
Die variable Tabelle ist nur für die aktuelle Sitzung verfügbar. Wenn Sie beispielsweise eine
EXEC
andere gespeicherte Prozedur innerhalb der aktuellen benötigen, müssen Sie die Tabelle übergeben, daTable Valued Parameter
dies natürlich die Leistung beeinträchtigt. Bei temporären Tabellen können Sie dies nur tun Übergabe des temporären TabellennamensSo testen Sie eine temporäre Tabelle:
So testen Sie eine Variablentabelle:
Ich habe Folgendes erlebt: Wenn Ihr Schema keine
GRANT
Berechtigung zum Erstellen von Tabellen hat, verwenden Sie variable Tabellen.quelle
Beim Schreiben von Daten in deklarierte Tabellen
declare @tb
und nach dem Verknüpfen mit anderen Tabellen wurde mir klar, dass die Antwortzeit im Vergleich zu temporären Tabellentempdb .. # tb
viel höher ist.Wenn ich sie mit @tb verbinde, ist die Zeit für die Rückgabe des Ergebnisses viel länger als bei #tm . Die Rückgabe erfolgt fast augenblicklich.
Ich habe Tests mit einem Join von 10.000 Zeilen und einem Join mit 5 anderen Tabellen durchgeführt
quelle