Gastautor:Derik Hammer (@SQLHammer)
Die Unterschiede zwischen TRUNCATE TABLE und DELETE werden oft missverstanden. Ich versuche, den Mythos zu widerlegen, dass TRUNCATE TABLE nicht rückgängig gemacht werden kann:
Lesen des Handbuchs
Der Books Online-Artikel zu TRUNCATE TABLE ist ziemlich beschreibend:
„Entfernt alle Zeilen aus einer Tabelle oder bestimmten Partitionen einer Tabelle, ohne die einzelnen Zeilenlöschungen zu protokollieren. TRUNCATE TABLE ähnelt der DELETE-Anweisung ohne WHERE-Klausel; TRUNCATE TABLE ist jedoch schneller und verwendet weniger System- und Transaktionsprotokollressourcen.“Die Tatsache, dass TRUNCATE TABLE weniger verwendet Transaktionslog-Ressourcen bedeutet, dass bis zu einem gewissen Grad in das Transaktionslog geschrieben wird. Lassen Sie uns herausfinden, wie viel, und untersuchen, ob ein Rollback möglich ist.
Beweisen Sie es
In einem früheren Beitrag geht Paul Randal dies akribisch im Detail durch, aber ich dachte, es wäre nützlich, sehr einfache Repros bereitzustellen, um beide Elemente dieses Mythos zu widerlegen.
Kann TRUNCATE TABLE rückgängig gemacht werden?
Der Nachweis, dass TRUNCATE TABLE rückgängig gemacht werden kann, ist recht einfach. Ich werde einfach TRUNCATE TABLE in eine Transaktion einfügen und sie rückgängig machen.
USE demo; BEGIN TRANSACTION; SELECT COUNT(*) [StartingTableRowCount] FROM [dbo].[Test]; TRUNCATE TABLE [dbo].[Test]; SELECT COUNT(*) [TableRowCountAfterTruncate] FROM [dbo].[Test]; ROLLBACK TRANSACTION; SELECT COUNT(*) [TableRowCountAfterRollback] FROM [dbo].[Test];
Die Tabelle enthält 100.000 Zeilen und kehrt nach dem Rollback zu 100.000 Zeilen zurück:
Schreibt TRUNCATE TABLE in das Protokoll?
Indem wir einen CHECKPOINT ausführen, erhalten wir einen sauberen Ausgangspunkt. Dann können wir die Protokollaufzeichnungen vor und nach der TRUNCATE TABLE überprüfen.
USE demo; CHECKPOINT; SELECT COUNT(*) [StartingLogRowCount] FROM sys.fn_dblog (NULL, NULL); TRUNCATE TABLE [dbo].[Test]; SELECT COUNT(*) [LogRowCountAfterTruncate] FROM sys.fn_dblog (NULL, NULL);
Unser TRUNCATE TABLE-Befehl generierte (zumindest anfänglich) 237 Protokollsätze. Auf diese Weise können wir ein Rollback durchführen und SQL Server registriert die Änderung von Anfang an.
Was ist mit LÖSCHEN?
Wenn sowohl DELETE als auch TRUNCATE TABLE in das Protokoll schreiben und zurückgesetzt werden können, was unterscheidet sie?
Wie oben in der BOL-Referenz erwähnt, beansprucht TRUNCATE TABLE weniger System- und Transaktionsprotokollressourcen. Wir haben bereits festgestellt, dass für den TRUNCATE TABLE-Befehl 237 Protokollsätze geschrieben wurden. Sehen wir uns nun DELETE.
anUSE demo; CHECKPOINT; SELECT COUNT(*) [StartingLogRowCount] FROM sys.fn_dblog (NULL, NULL); DELETE FROM [dbo].[Test]; SELECT COUNT(*) [LogRowCountAfterDelete] FROM sys.fn_dblog (NULL, NULL);
Mit über 440.000 für DELETE geschriebenen Protokolldatensätzen ist der TRUNCATE-Befehl eindeutig viel effizienter.
Zusammenfassung
TRUNCATE TABLE ist ein protokollierter Befehl und kann rückgängig gemacht werden, mit einem enormen Leistungsvorteil gegenüber einem entsprechenden DELETE. DELETE wird wichtig, wenn Sie weniger Zeilen löschen möchten, als in der Tabelle vorhanden sind (da TRUNCATE TABLE keine WHERE-Klausel akzeptiert). Einige Ideen, wie DELETE-Operationen effizienter gestaltet werden können, finden Sie in Aaron Bertrands Post „Break large delete operations into chunks.“