In SQL Server 2005 können Sie temporäre Tabellen auf zwei Arten erstellen:
declare @tmp table (Col1 int, Col2 int);
oder
create table #tmp (Col1 int, Col2 int);
Was sind die Unterschiede zwischen diesen beiden? Ich habe widersprüchliche Meinungen darüber gelesen, ob @tmp noch Tempdb verwendet oder ob alles im Speicher passiert.
In welchen Szenarien übertrifft einer den anderen?
sql-server
temp-tables
table-variable
Eric Z Bart
quelle
quelle
Antworten:
Es gibt einige Unterschiede zwischen temporären Tabellen (#tmp) und Tabellenvariablen (@tmp), obwohl die Verwendung von tempdb keine davon ist, wie im folgenden MSDN-Link beschrieben.
Als Faustregel gilt, dass Sie für kleine bis mittlere Datenmengen und einfache Verwendungsszenarien Tabellenvariablen verwenden sollten. (Dies ist eine zu breite Richtlinie mit natürlich vielen Ausnahmen - siehe unten und folgende Artikel.)
Einige Punkte, die bei der Auswahl zu beachten sind:
Temporäre Tabellen sind echte Tabellen, sodass Sie beispielsweise INDEXE ERSTELLEN usw. können. Wenn Sie über große Datenmengen verfügen, für die der Zugriff per Index schneller ist, sind temporäre Tabellen eine gute Option.
Tabellenvariablen können mithilfe von PRIMARY KEY- oder UNIQUE-Einschränkungen Indizes haben. (Wenn Sie einen nicht eindeutigen Index möchten, fügen Sie einfach die Primärschlüsselspalte als letzte Spalte in die eindeutige Einschränkung ein. Wenn Sie keine eindeutige Spalte haben, können Sie eine Identitätsspalte verwenden.) SQL 2014 verfügt auch über nicht eindeutige Indizes .
Tabellenvariablen nehmen nicht an Transaktionen teil und
SELECT
s sind implizit mitNOLOCK
. Das Transaktionsverhalten kann sehr hilfreich sein. Wenn Sie beispielsweise mitten in einer Prozedur ROLLBACKEN möchten, werden die während dieser Transaktion aufgefüllten Tabellenvariablen weiterhin ausgefüllt.Temp-Tabellen können dazu führen, dass gespeicherte Prozeduren möglicherweise häufig neu kompiliert werden. Tabellenvariablen werden nicht.
Sie können eine temporäre Tabelle mit SELECT INTO erstellen, die schneller zu schreiben ist (gut für Ad-hoc-Abfragen geeignet) und es Ihnen möglicherweise ermöglicht, sich im Laufe der Zeit mit sich ändernden Datentypen zu befassen, da Sie Ihre temporäre Tabellenstruktur nicht im Voraus definieren müssen.
Sie können Tabellenvariablen von Funktionen zurückgeben, wodurch Sie die Logik viel einfacher kapseln und wiederverwenden können (z. B. eine Funktion zum Teilen einer Zeichenfolge in eine Wertetabelle in einem beliebigen Trennzeichen erstellen).
Durch die Verwendung von Tabellenvariablen in benutzerdefinierten Funktionen können diese Funktionen häufiger verwendet werden (Einzelheiten finden Sie in der Dokumentation zu CREATE FUNCTION). Wenn Sie eine Funktion schreiben, sollten Sie Tabellenvariablen über temporäre Tabellen verwenden, sofern nicht zwingend etwas anderes erforderlich ist.
Sowohl Tabellenvariablen als auch temporäre Tabellen werden in tempdb gespeichert. Tabellenvariablen (seit 2005) verwenden standardmäßig die Sortierung der aktuellen Datenbank im Vergleich zu temporären Tabellen, die die Standardkollatierung von tempdb ( ref ) verwenden. Dies bedeutet, dass Sie sich der Sortierprobleme bewusst sein sollten, wenn Sie temporäre Tabellen verwenden und Ihre Datenbankkollatierung sich von der temporären unterscheidet. Dies führt zu Problemen, wenn Sie Daten in der temporären Tabelle mit Daten in Ihrer Datenbank vergleichen möchten.
Globale temporäre Tabellen (## tmp) sind eine andere Art von temporären Tabellen, die allen Sitzungen und Benutzern zur Verfügung stehen.
Einige weiterführende Literatur:
Martin Smiths großartige Antwort auf dba.stackexchange.com
Häufig gestellte Fragen zu MSDN zum Unterschied zwischen beiden: https://support.microsoft.com/en-gb/kb/305977
MDSN-Blogartikel: https://docs.microsoft.com/archive/blogs/sqlserverstorageengine/tempdb-table-variable-vs-local-temporary-table
Artikel: https://searchsqlserver.techtarget.com/tip/Temporary-tables-in-SQL-Server-vs-table-variables
Unerwartetes Verhalten und Auswirkungen auf die Leistung von temporären Tabellen und temporären Variablen: Paul White auf SQLblog.com
quelle
Betrachten Sie nur die Behauptung in der akzeptierten Antwort, dass Tabellenvariablen nicht an der Protokollierung teilnehmen.
Es scheint im Allgemeinen nicht wahr zu sein, dass es einen Unterschied in der Menge der Protokollierung gibt (zumindest für
insert
/update
/delete
Operationen an der Tabelle selbst, obwohl ich seitdem festgestellt habe, dass diesbezüglich einige kleine Unterschiede für zwischengespeicherte temporäre Objekte in gespeicherten Prozeduren aufgrund zusätzlicher Systemtabellen bestehen Aktualisierung).Ich habe das Protokollierungsverhalten sowohl für eine
@table_variable
als auch für eine#temp
Tabelle für die folgenden Vorgänge untersucht.Die Transaktionsprotokolldatensätze waren für alle Vorgänge nahezu identisch.
Die Tabellenvariablenversion enthält tatsächlich einige zusätzliche Protokolleinträge, da ein Eintrag zur Basistabelle hinzugefügt (und später aus dieser entfernt) wird.
sys.syssingleobjrefs
Insgesamt wurden jedoch einige weniger Bytes protokolliert, da der interne Name für Tabellenvariablen 236 Bytes weniger verbraucht als für#temp
Tabellen (118 wenigernvarchar
Zeichen).Vollständiges Skript zum Reproduzieren (am besten auf einer Instanz ausführen, die im Einzelbenutzermodus und im Verwendungsmodus gestartet wurde
sqlcmd
)Ergebnisse
quelle
INSERT ... SELECT
nicht minimal protokolliert wurden und Sie keineSELECT INTO ...
Tabellenvariable können.Verwenden Sie für kleinere Tabellen (weniger als 1000 Zeilen) eine temporäre Variable, andernfalls eine temporäre Tabelle.
quelle
@wcm - um die Tabellenvariable nicht auszuwählen, ist sie nicht nur Ram - sie kann teilweise auf der Festplatte gespeichert werden.
Eine temporäre Tabelle kann Indizes haben, während eine Tabellenvariable nur einen Primärindex haben kann. Wenn Geschwindigkeit ein Problem ist, können Tabellenvariablen schneller sein. Wenn jedoch viele Datensätze vorhanden sind oder die temporäre Tabelle eines Clustered-Index durchsucht werden muss, ist eine temporäre Tabelle besser.
Guter Hintergrundartikel
quelle
Temp-Tabelle: Eine Temp-Tabelle ist einfach zu erstellen und Daten zu sichern.
Tabellenvariable: Die Tabellenvariable ist jedoch mit dem Aufwand verbunden, wenn normalerweise die normalen Tabellen erstellt werden.
Temp-Tabelle: Das Ergebnis der Temp-Tabelle kann von mehreren Benutzern verwendet werden.
Tabellenvariable: Die Tabellenvariable kann jedoch nur vom aktuellen Benutzer verwendet werden.
Temp-Tabelle: Die Temp-Tabelle wird in der Tempdb gespeichert. Es wird Netzwerkverkehr machen. Wenn die temporäre Tabelle große Datenmengen enthält, muss diese in der gesamten Datenbank funktionieren. Es liegt ein Leistungsproblem vor.
Tabellenvariable: Eine Tabellenvariable wird jedoch für einige Daten im physischen Speicher gespeichert. Später, wenn die Größe zunimmt, wird sie in die temporäre Datenbank verschoben.
Temp-Tabelle: Die Temp-Tabelle kann alle DDL-Operationen ausführen. Es ermöglicht das Erstellen der Indizes, das Löschen, Ändern usw.
Tabellenvariable: Während die Tabellenvariable die DDL-Operationen nicht zulässt. Mit der Tabellenvariablen können wir jedoch nur den Clustered-Index erstellen.
Temp-Tabelle: Die Temp-Tabelle kann für die aktuelle Sitzung oder global verwendet werden. Damit eine Sitzung mit mehreren Benutzern die Ergebnisse in der Tabelle verwenden kann.
Tabellenvariable: Die Tabellenvariable kann jedoch bis zu diesem Programm verwendet werden. (Gespeicherte Prozedur)
Temp-Tabelle: Die Temp-Variable kann die Transaktionen nicht verwenden. Wenn wir die DML-Operationen mit der temporären Tabelle ausführen, kann dies ein Rollback sein oder die Transaktionen festschreiben.
Tabellenvariable: Für Tabellenvariablen ist dies jedoch nicht möglich.
Temp-Tabelle: Funktionen können die Temp-Variable nicht verwenden. Darüber hinaus können wir die DML-Operation in den Funktionen nicht ausführen.
Tabellenvariable: Mit dieser Funktion können wir jedoch die Tabellenvariable verwenden. Aber mit der Tabellenvariablen können wir das tun.
Temp-Tabelle: Die gespeicherte Prozedur führt die Neukompilierung durch (kann nicht denselben Ausführungsplan verwenden), wenn wir die temporäre Variable für jeden nachfolgenden Aufruf verwenden.
Tabellenvariable: Während die Tabellenvariable so nicht funktioniert.
quelle
Für alle, die an den Mythos glauben, dass temporäre Variablen nur im Speicher sind
Erstens ist die Tabellenvariable NICHT unbedingt speicherresident. Unter Speicherdruck können die zu einer Tabellenvariablen gehörenden Seiten nach tempdb verschoben werden.
Lesen Sie den Artikel hier: TempDB :: Tabellenvariable vs. lokale temporäre Tabelle
quelle
Der andere Hauptunterschied besteht darin, dass Tabellenvariablen keine Spaltenstatistik haben, wie dies bei temporären Tabellen der Fall ist. Dies bedeutet, dass der Abfrageoptimierer nicht weiß, wie viele Zeilen sich in der Tabellenvariablen befinden (er schätzt 1), was dazu führen kann, dass höchst nicht optimale Pläne generiert werden, wenn die Tabellenvariable tatsächlich eine große Anzahl von Zeilen enthält.
quelle
rows
Spalte insys.partitions
wird für Tabellenvariablen verwaltet, damit sie tatsächlich weiß, wie viele Zeilen sich in der Tabelle befinden. Dies kann mit gesehen werdenOPTION (RECOMPILE)
. Das Fehlen von Spaltenstatistiken bedeutet jedoch, dass bestimmte Spaltenprädikate nicht geschätzt werden können.Zitat aus; Professional SQL Server 2012-Interna und Fehlerbehebung
TABELLENVARIABLEN WERDEN NICHT IM SPEICHER ERSTELLT
Es gibt ein weit verbreitetes Missverständnis, dass Tabellenvariablen speicherinterne Strukturen sind und daher schneller als temporäre Tabellen arbeiten . Dank einer DMV namens sys. dm _ db _ session _ space _ usage, die die tempdb-Nutzung nach Sitzung anzeigt. Sie können beweisen, dass dies nicht der Fall ist . Führen Sie nach dem Neustart von SQL Server zum Löschen der DMV das folgende Skript aus, um zu bestätigen, dass Ihre Sitzungs-ID 0 für Benutzerobjekte _zuweisung _ Seitenanzahl _ zurückgibt:
Jetzt können Sie überprüfen, wie viel Speicherplatz eine temporäre Tabelle belegt, indem Sie das folgende Skript ausführen, um eine temporäre Tabelle mit einer Spalte zu erstellen und mit einer Zeile zu füllen:
Die Ergebnisse auf meinem Server zeigen an, dass der Tabelle eine Seite in Tempdb zugewiesen wurde. Führen Sie nun dasselbe Skript aus, verwenden Sie diesmal jedoch eine Tabellenvariable:
Welches verwenden?
quelle
Noch ein Unterschied:
Auf eine Tabelle var kann nur über Anweisungen innerhalb der Prozedur zugegriffen werden, die sie erstellt, nicht über andere Prozeduren, die von dieser Prozedur aufgerufen werden, oder über verschachteltes dynamisches SQL (über exec oder sp_executesql).
Der Gültigkeitsbereich einer temporären Tabelle umfasst dagegen Code in aufgerufenen Prozeduren und verschachteltem dynamischem SQL.
Wenn auf die von Ihrer Prozedur erstellte Tabelle über andere aufgerufene Prozeduren oder dynamisches SQL zugegriffen werden muss, müssen Sie eine temporäre Tabelle verwenden. Dies kann in komplexen Situationen sehr praktisch sein.
quelle
Unterschiede zwischen
Temporary Tables (##temp/#temp)
undTable Variables (@table)
sind wie folgt :Table variable (@table)
wird in der erstelltmemory
. Während aTemporary table (##temp/#temp)
in der erstellt wirdtempdb database
. Bei Speicherdruck können die zu einer Tabellenvariablen gehörenden Seiten jedoch auf tempdb verschoben werden.Table variables
kann nicht beteiligt seintransactions, logging or locking
. Das macht@table faster then #temp
. Die Tabellenvariable ist also schneller als die temporäre Tabelle.Temporary table
erlaubt Schemaänderungen im Gegensatz zuTable variables
.Temporary tables
sind in der erstellten Routine und auch in den untergeordneten Routinen sichtbar. Während Tabellenvariablen nur in der erstellten Routine sichtbar sind.Temporary tables
sind erlaubt,CREATE INDEXes
währendTable variables
nicht erlaubt sind,CREATE INDEX
stattdessen können sie Index mit verwendenPrimary Key or Unique Constraint
.quelle
Bedenken Sie auch, dass Sie beide häufig durch abgeleitete Tabellen ersetzen können, die möglicherweise auch schneller sind. Wie bei jeder Leistungsoptimierung können jedoch nur tatsächliche Tests anhand Ihrer tatsächlichen Daten den besten Ansatz für Ihre spezielle Abfrage ermitteln.
quelle
Es überrascht mich, dass niemand den Hauptunterschied zwischen diesen beiden erwähnt hat, dass die temporäre Tabelle das parallele Einfügen unterstützt , während die Tabellenvariable dies nicht tut. Sie sollten in der Lage sein, den Unterschied zum Ausführungsplan zu erkennen. Und hier ist das Video von SQL Workshops auf Kanal 9 .
Dies erklärt auch, warum Sie eine temporäre Variable für kleinere Tabellen verwenden sollten, andernfalls eine temporäre Tabelle, wie SQLMenace zuvor geantwortet hat.
quelle