sql >> Database teknologi >  >> RDS >> Database

Ydelsesmyter:Truncate kan ikke rulles tilbage

Gæsteforfatter:Derik Hammer (@SQLHammer)


Forskellene mellem TRUNCATE TABLE og DELETE bliver ofte misforstået. Jeg søger at modbevise myten om, at TRUNCATE TABLE ikke kan rulles tilbage:

"TRUNCATE TABLE er ikke logget og kan derfor ikke rulles tilbage. Du skal bruge DELETE, hvis du er i en transaktion."

Læsning af manualen

Books Online-artiklen om TRUNCATE TABLE er ret beskrivende:

"Fjerner alle rækker fra en tabel eller specificerede partitioner i en tabel uden at logge de enkelte rækkesletninger. TRUNCATE TABLE ligner DELETE-sætningen uden WHERE-sætning; TRUNCATE TABLE er dog hurtigere og bruger færre system- og transaktionslogressourcer."

Det faktum, at TRUNCATE TABLE bruger færre transaktionslogressourcer indebærer, at den skriver til transaktionsloggen til en vis grad. Lad os finde ud af hvor meget og undersøge dets evne til at blive rullet tilbage.

Bevis det

I et tidligere indlæg gennemgår Paul Randal dette omhyggeligt, men jeg tænkte, at det ville være nyttigt at give meget simple repros for at modbevise begge elementer i denne myte.

Kan TRUNCATE TABLE rulles tilbage?

Det er nemt nok at bevise, at TRUNCATE TABLE kan rulles tilbage. Jeg vil simpelthen sætte TRUNCATE TABLE i en transaktion og rulle den tilbage.

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];

Der er 100.000 rækker i tabellen, og den vender tilbage til 100.000 rækker efter tilbagerulning:

Skriver TRUNCATE TABLE til loggen?

Ved at udføre et CHECKPOINT får vi et rent udgangspunkt. Så kan vi kontrollere logposterne før og 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);

Vores TRUNCATE TABLE-kommando genererede 237 logposter (i det mindste i begyndelsen). Det er det, der gør os i stand til at udføre en tilbagerulning, og hvordan SQL Server registrerer ændringen til at begynde med.

Hvad med DELETEs?

Hvis både DELETE og TRUNCATE TABLE skriver til loggen og kan rulles tilbage, hvad gør dem så anderledes?

Som nævnt i BOL-referencen ovenfor, tager TRUNCATE TABLE færre system- og transaktionslogressourcer. Vi har allerede observeret, at 237 logposter blev skrevet til TRUNCATE TABLE-kommandoen. Lad os nu se 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 over 440.000 logposter skrevet til DELETE, er TRUNCATE-kommandoen klart meget mere effektiv.

Afslutning

TRUNCATE TABLE er en logget kommando og kan rulles tilbage, med en kæmpe fordel i forhold til en tilsvarende DELETE. DELETE bliver vigtigt, når du ønsker at slette færre rækker, end der findes i tabellen (da TRUNCATE TABLE ikke accepterer en WHERE-sætning). For nogle ideer til at gøre DELETEs mere effektive, se Aaron Bertrands indlæg, "Opdel store sletningsoperationer i bidder."

Om forfatteren

Derik er en dataprofessionel og nyudviklet Microsoft Data Platform MVP med fokus på SQL Server. Hans passion fokuserer på høj tilgængelighed, katastrofegendannelse, kontinuerlig integration og automatiseret vedligeholdelse. Hans erfaring har spændt over langsigtet databaseadministration, rådgivning og iværksættervirksomheder, der arbejder i finans- og sundhedsindustrien. Han er i øjeblikket Senior Database Administrator med ansvar for Database Operations-teamet på Subway Franchise World Headquarters. Når han ikke er på uret eller blogger på SQLHammer.com, afsætter Derik sin tid til #sqlfamily som kapitelleder for FairfieldPASS SQL Server-brugergruppen i Stamford, CT.
  1. Stjerneskemaet

  2. Hvordan får man sidste indsættelses-id i Oracle ved hjælp af MyBatis?

  3. Hvordan Radians()-funktionen fungerer i PostgreSQL

  4. Hvordan forespørges feltet DATETIME kun ved hjælp af dato i Microsoft SQL Server?