it-swarm-eu.dev

SQL Server "prázdná tabulka" je pomalý po odstranění všech (12 milionů) záznamů?

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?!?

27
TheDramaLlama

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:

Proč je 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 .

42
Remus Rusanu

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
13
Akhil

(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:

  • Využití prostoru žurnálu: TRUNCATE protokolová pouze stránky/rozsahy * uvolněné, zatímco DELETE zaznamenává jednotlivé řádky.
  • Použití zámku: 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>' afterTRUNCATE/DELETE`, takže optimalizátor dotazů se nezachytí starými statistikami.

3
Simon Righarts

(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.

2
DaveE