Gästförfattare:Derik Hammer (@SQLHammer)
Skillnaderna mellan TRUNCATE TABLE och DELETE missförstås ofta. Jag försöker motbevisa myten att TRUNCATE TABLE inte kan rullas tillbaka:
Läser manualen
Books Online-artikeln om TRUNCATE TABLE är ganska beskrivande:
"Tar bort alla rader från en tabell eller specificerade partitioner av en tabell, utan att logga de enskilda radraderingarna. TRUNCATE TABLE liknar DELETE-satsen utan någon WHERE-sats; TRUNCATE TABLE är dock snabbare och använder färre system- och transaktionsloggresurser."Det faktum att TRUNCATE TABLE använder färre transaktionsloggresurser innebär att den skriver till transaktionsloggen till viss del. Låt oss ta reda på hur mycket och undersöka dess förmåga att rullas tillbaka.
Bevisa det
I ett tidigare inlägg går Paul Randal igenom detta noggrant, men jag tänkte att det skulle vara användbart att ge mycket enkla repros för att motbevisa båda delarna av denna myt.
Kan TRUNCATE TABLE återställas?
Att bevisa att TRUNCATE TABLE kan rullas tillbaka är lätt nog. Jag lägger helt enkelt TRUNCATE TABLE i en transaktion och återställer den.
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];
Det finns 100 000 rader i tabellen och den återgår till 100 000 rader efter återställning:
Skriver TRUNCATE TABLE till loggen?
Genom att utföra en CHECKPOINT får vi en ren utgångspunkt. Sedan kan vi kontrollera loggposterna före och efter TRUNCATE TABLE.
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);
Vårt TRUNCATE TABLE-kommando genererade 237 loggposter (åtminstone initialt). Detta är vad som gör det möjligt för oss att utföra en återställning och hur SQL Server registrerar ändringen till att börja med.
Vad sägs om DELETEs?
Om både DELETE och TRUNCATE TABLE skriver till loggen och kan rullas tillbaka, vad är det som skiljer dem?
Som nämnts i BOL-referensen ovan tar TRUNCATE TABLE färre system- och transaktionsloggresurser. Vi har redan observerat att 237 loggposter skrevs för kommandot TRUNCATE TABLE. Låt oss nu titta på DELETE.
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);
Med över 440 000 loggposter skrivna för DELETE är kommandot TRUNCATE helt klart mycket mer effektivt.
Avslutning
TRUNCATE TABLE är ett loggat kommando och kan rullas tillbaka, med en enorm prestandafördel jämfört med en motsvarande DELETE. DELETE blir viktigt när du vill ta bort färre rader än vad som finns i tabellen (eftersom TRUNCATE TABLE inte accepterar en WHERE-sats). För några idéer om att göra DELETEs effektivare, se Aaron Bertrands inlägg, "Dela upp stora raderingsoperationer i bitar."