Gastauteur:Derik Hammer (@SQLHammer)
De verschillen tussen TRUNCATE TABLE en DELETE worden vaak verkeerd begrepen. Ik probeer de mythe te weerleggen dat TRUNCATE TABLE niet kan worden teruggedraaid:
De handleiding lezen
Het Books Online-artikel over TRUNCATE TABLE is redelijk beschrijvend:
“Verwijdert alle rijen uit een tabel of gespecificeerde partities van een tabel, zonder de individuele rijverwijderingen vast te leggen. TRUNCATE TABLE lijkt op de DELETE-instructie zonder WHERE-clausule; TRUNCATE TABLE is echter sneller en gebruikt minder systeem- en transactielogboekbronnen.”Het feit dat TRUNCATE TABLE minder . gebruikt transactielogboekbronnen houdt in dat het tot op zekere hoogte naar het transactielogboek schrijft. Laten we eens kijken hoeveel en onderzoeken of het kan worden teruggedraaid.
Bewijs het
In een eerdere post gaat Paul Randal hier minutieus op in, maar ik dacht dat het nuttig zou zijn om heel eenvoudige herhalingen te geven om beide elementen van deze mythe te weerleggen.
Kan TRUNCATE TABLE worden teruggedraaid?
Bewijzen dat TRUNCATE TABLE kan worden teruggedraaid, is eenvoudig genoeg. Ik zal gewoon TRUNCATE TABLE in een transactie plaatsen en het terugdraaien.
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];
Er zijn 100.000 rijen in de tabel en deze keert terug naar 100.000 rijen na het terugdraaien:
Schrijft TRUNCATE TABLE naar het logboek?
Door een CHECKPOINT uit te voeren, krijgen we een schoon startpunt. Dan kunnen we de logrecords voor en na de TRUNCATE TABLE controleren.
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);
Ons TRUNCATE TABLE-commando genereerde 237 logrecords (tenminste aanvankelijk). Dit is wat ons in staat stelt om een rollback uit te voeren, en hoe SQL Server de wijziging registreert om mee te beginnen.
Hoe zit het met VERWIJDEREN?
Als zowel DELETE als TRUNCATE TABLE naar het logboek schrijven en teruggedraaid kunnen worden, wat maakt ze dan anders?
Zoals vermeld in de BOL-referentie hierboven, neemt TRUNCATE TABLE minder systeem- en transactielogboekbronnen in beslag. We zagen al dat er 237 logrecords zijn geschreven voor het TRUNCATE TABLE-commando. Laten we nu eens kijken naar de VERWIJDEREN.
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);
Met meer dan 440.000 logrecords geschreven voor DELETE, is het TRUNCATE-commando duidelijk veel efficiënter.
Afronding
TRUNCATE TABLE is een gelogde opdracht en kan worden teruggedraaid, met een enorm prestatievoordeel ten opzichte van een gelijkwaardige DELETE. DELETE wordt belangrijk wanneer u minder rijen wilt verwijderen dan er in de tabel staan (aangezien TRUNCATE TABLE geen WHERE-clausule accepteert). Voor enkele ideeën over het efficiënter maken van VERWIJDEREN, zie het bericht van Aaron Bertrand, "Breek grote verwijderingsbewerkingen in stukken."