Autor hosta :Derik Hammer (@SQLHammer)
Rozdíly mezi TRUNCATE TABLE a DELETE jsou často nepochopeny. Snažím se vyvrátit mýtus, že TRUNCATE TABLE nelze vrátit zpět:
Čtení návodu
Článek Books Online na TRUNCATE TABLE je poměrně popisný:
„Odebere všechny řádky z tabulky nebo zadaných oddílů tabulky, aniž by protokoloval odstranění jednotlivých řádků. TRUNCATE TABLE je podobná příkazu DELETE bez klauzule WHERE; ale TRUNCATE TABLE je rychlejší a využívá méně prostředků systému a transakčního protokolu.“Skutečnost, že TRUNCATE TABLE používá méně prostředky protokolu transakcí znamená, že do určité míry zapisuje do protokolu transakcí. Pojďme zjistit, kolik a prozkoumat jeho schopnost být vrácena zpět.
Dokažte to
V dřívějším příspěvku to Paul Randal podrobně probírá, ale myslel jsem si, že by bylo užitečné poskytnout velmi jednoduché opakování, aby se vyvrátily oba prvky tohoto mýtu.
Lze TRUNCATE TABLE vrátit zpět?
Dokázat, že TRUNCATE TABLE lze vrátit zpět, je dostatečně snadné. Jednoduše vložím TRUNCATE TABLE do transakce a vrátím ji zpět.
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];
V tabulce je 100 000 řádků a po vrácení se vrátí na 100 000 řádků:
Zapisuje TRUNCATE TABLE do protokolu?
Provedením CHECKPOINT získáme čistý výchozí bod. Poté můžeme zkontrolovat záznamy protokolu před a za TABLE ZKRÁTENÍ.
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);
Náš příkaz TRUNCATE TABLE vygeneroval 237 záznamů protokolu (alespoň zpočátku). To je to, co nám umožňuje provést vrácení zpět a jak SQL Server nejprve zaregistruje změnu.
A co DELETE?
Pokud DELETE i TRUNCATE TABLE zapisují do protokolu a lze je vrátit zpět, čím se liší?
Jak je uvedeno v odkazu BOL výše, TRUNCATE TABLE vyžaduje méně prostředků systému a protokolu transakcí. Již jsme si všimli, že pro příkaz TRUNCATE TABLE bylo zapsáno 237 záznamů protokolu. Nyní se podívejme na 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);
S více než 440 000 záznamy protokolu zapsanými pro DELETE je příkaz TRUNCATE jednoznačně mnohem efektivnější.
Shrnutí
TRUNCATE TABLE je zaprotokolovaný příkaz a lze jej vrátit zpět s obrovskou výkonnostní výhodou oproti ekvivalentnímu DELETE. DELETE je důležité, když chcete odstranit méně řádků, než existuje v tabulce (protože TRUNCATE TABLE nepřijímá klauzuli WHERE). Některé nápady, jak zefektivnit DELETE, najdete v příspěvku Aarona Bertranda „Rozdělit velké operace mazání na kousky.“