Mám instanci serveru SQL Server 2008 s přibližně 150 sloupci. Dříve jsem tuto tabulku naplnil přibližně 12 miliony záznamů, ale od té doby jsem ji vyčistil v rámci přípravy na nový soubor dat.
Avšak příkazy, které kdysi běžely okamžitě na prázdné tabulce, jako například count(*)
a select top 1000
V SQL Management Studio
, Nyní zabírají věky.
SELECT COUNT(*) FROM TABLE_NAME
trvalo více než 11 minut, než se vrátí 0, a SELECT TOP 1000
trvalo téměř 10 minut, než se vrátila prázdná tabulka.
Také jsem si všiml, že volné místo na mém pevném disku doslova zmizelo (z asi 100 G na 20 G). Jediná věc, která se mezi tím stala, byl jediný dotaz, který jsem spustil:
DELETE FROM TABLE_NAME
Co se to ve světě děje?!?
Už vám bylo řečeno o tom, proč by TRUNCATE
bylo mnohem rychlejší/lepší/svůdnější než DELETE
, ale stále ještě zbývá otázka:
SELECT
pomalejší po dokončení DELETE
?To proto, že DELETE
má pouze duchové řádky. Tabulka je stejně velká jako když měla 12M řádků, i když nemá. Chcete-li spočítat řádky (0), trvá tolik času, kolik trvalo, než se počítá 12M řádků. Časem bude proces čištění duchů odpadky shromažďovat tyto duchové záznamy a přidělovat stránky, které obsahovaly pouze duchové, a vaše VÝBORY se zrychlí. Ale právě teď, pokud zaškrtnete Skipped Ghosted Records/sec
ve perfmonu pravděpodobně stoupá během SELECT COUNT(*)
. Věci můžete také urychlit obnovením tabulky: ALTER TABLE ... REBUILD
.
TRUNCATE
by se o tento problém také postaral, protože nezanechává žádné duchy.
Viz také vnitř úložiště: hloubka vyčištění ducha .
Příkazy DELETE
odstraňují řádky z tabulky jeden po druhém, zaznamenávají každý řádek do transaction log
a také udržují informace log sequence number (LSN)
. Protože jste zmínili, že vaše tabulka obsahuje obrovská data (12 milionů záznamů), po vymazání místa na pevném disku není dostatek místa, zkontrolujte velikost souboru protokolu databáze. Pravděpodobně by to rostlo.
lepší cesta by byla:
TRUNCATE TABLE_NAME
(Toto byl původně komentář k odpovědi @ DaveE, ale vložil jsem to do své vlastní odpovědi, protože to bylo dlouhé)
TRUNCATE
je protokolovaná operace. Musí to být jinak, není to ACID-kompatibilní. Rozdíly mezi TRUNCATE
a DELETE
:
TRUNCATE
protokolová pouze stránky/rozsahy * uvolněné, zatímco DELETE
zaznamenává jednotlivé řádky.TRUNCATE
bude obecně používat méně zámků, protože vyžaduje blokování tabulek a zámek stránek, na rozdíl od DELETE
, který používá zámky řádků **.IDENTITY
sekvence: TRUNCATE
vynuluje sekvenci identity v tabulce, pokud existuje.(* Rozsah = 8 stránek. TRUNCATE
bude protokolovat/odstraňovat rozsahy, pokud jsou všechny z jedné tabulky, jinak bude protokolovat/odstraňovat stránky ze smíšených rozsahů.
** Jedním z vedlejších účinků je to, že DELETE FROM TABLE
může potenciálně ponechat prázdné stránky přidělené tabulce, v závislosti na tom, zda operace může získat výhradní zámek tabulky nebo ne.)
Takže (zpět k původní otázce), TRUNCATE TABLE
je přesvědčivě lepší než DELETE FROM TABLE
Pokud vyprazdňujete tabulku, ale chcete zachovat strukturu (Pozn .: TRUNCATE
nelze použít v tabulce, na kterou odkazuje cizí klíč z jiné tabulky).
Jak je uvedeno v komentáři @ Tullo, podívejte se také na model obnovy vaší databáze - pokud je plný, pak musíte buď začít zálohovat protokoly, nebo změnit model obnovy na jednoduchý. Jakmile některý z nich uděláte, pravděpodobně budete chtít zmenšit soubor protokolu jako jednorázovou operaci (Pozn .: soubor protokolu - pouze) za účelem získání veškerého volného místa.
A konečně, další věc, kterou si musíte uvědomit - stolní statistiky. spustit UPDATE STATISTICS <TABLENAME>' after
TRUNCATE/
DELETE`, takže optimalizátor dotazů se nezachytí starými statistikami.
(POZNÁMKA: Nejsem DBA) DELETE je protokolovaná operace a neuvolňuje použité místo. Pravděpodobně máte velký protokol transakcí zabírající místo a skenování tabulek spuštěné v „prázdném“ tabulkovém prostoru. Hádám, že musíte vymazat protokol transakcí a zmenšit databázi. Tento článek StackOverflow by vás měl začít.
A použijte TRUNCATE TABLE, pokud to chcete udělat v budoucnu.
ÚPRAVA: Můj výrok o tom, že TRUNCATE není přihlášen, byl chybný. odstraněn.