Database
 sql >> Datenbank >  >> RDS >> Database

Leistungsmythen:Truncate kann nicht rückgängig gemacht werden

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:

„TRUNCATE TABLE wird nicht protokolliert und kann daher nicht rückgängig gemacht werden. Sie müssen DELETE verwenden, wenn Sie sich in einer Transaktion befinden.“

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.

an
USE 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.“

Über den Autor

Derik ist ein Datenexperte und frisch gebackener Microsoft Data Platform MVP mit Schwerpunkt auf SQL Server. Seine Leidenschaft konzentriert sich auf Hochverfügbarkeit, Disaster Recovery, kontinuierliche Integration und automatisierte Wartung. Seine Erfahrung umfasst langfristige Datenbankverwaltung, Beratung und unternehmerische Unternehmungen in der Finanz- und Gesundheitsbranche. Derzeit ist er Senior Database Administrator und verantwortlich für das Database Operations-Team bei Subway Franchise World Headquarters. Wenn er nicht auf der Uhr ist oder auf SQLHammer.com bloggt, widmet Derik seine Zeit der #sqlfamily als Kapitelleiter der FairfieldPASS SQL Server-Benutzergruppe in Stamford, CT.