Mam instancję SQL Server 2008 z około 150 kolumnami. Wcześniej wypełniłem tę tabelę około 12 milionami wpisów, ale odtąd wyczyściłem tabelę w ramach przygotowań do nowego zestawu danych.
Jednak polecenia, które prowadził kiedyś od razu w pustym stole, takie jak count(*)
i select top 1000
na SQL Management Studio
teraz podjąć eony uruchomić.
SELECT COUNT(*) FROM TABLE_NAME
zwrócenie 0 zajęło ponad 11 minut, a SELECT TOP 1000
powrót pustego stolika zajęło prawie 10 minut.
Zauważyłem również, że wolne miejsce na moim dysku twardym dosłownie zniknęło (z około 100G do 20G). Jedyne, co się wydarzyło, to jedno zapytanie, które uruchomiłem:
DELETE FROM TABLE_NAME
Co się dzieje na świecie?!?
TRUNCATE TABLE
zamiastDELETE FROM
.Odpowiedzi:
Powiedziano ci już, dlaczego
TRUNCATE
byłby o wiele szybszy / lepszy / seksowniejszyDELETE
, ale wciąż pozostaje pytanie:Dlaczego
SELECT
poDELETE
zakończeniu działa wolniej ?To dlatego,
DELETE
że tylko widmo wierszy. Tabela jest tak duża, jak wtedy, gdy miała 12 mln wierszy, nawet jeśli nie ma. Aby zliczyć rzędy (0), zajmuje tyle samo czasu, ile potrzeba, aby zliczyć 12 milionów wierszy. Z czasem proces czyszczenia duchów usunie te duchowe rekordy i cofnie przydział stron, które zawierały tylko duchy, a twoje SELECT przyspieszy. Ale teraz, jeśli zameldujesz sięSkipped Ghosted Records/sec
w perfmon, prawdopodobnie gwałtownie rośnieSELECT COUNT(*)
. Można również przyspieszyć rzeczy poprzez przebudowę tabeli:ALTER TABLE ... REBUILD
.TRUNCATE
zająłby się także tym problemem, ponieważ nie pozostawia po sobie żadnych duchów.Zobacz także Inside the Storage Engine: Dogłębne czyszczenie duchów .
źródło
DELETE
instrukcje usuwają wiersze z tabeli pojedynczo, rejestrując każdy wiersz wtransaction log
, a także zachowująclog sequence number (LSN)
informacje. Ponieważ wspomniano, że w tabeli znajdują się ogromne dane (12 milionów rekordów), po usunięciu którego na dysku twardym brakuje miejsca, sprawdź rozmiar pliku dziennika bazy danych. Najprawdopodobniej urósłoby.Lepszym sposobem byłoby:
źródło
(To był pierwotnie komentarz do odpowiedzi @ DaveE, ale umieściłem go we własnej odpowiedzi, ponieważ stał się długi)
TRUNCATE
jest zarejestrowaną operacją. Musi być inaczej, ponieważ nie jest zgodny z ACID. Jednak różnice międzyTRUNCATE
iDELETE
:TRUNCATE
zwalnia tylko strony / zakresy *, podczas gdyDELETE
rejestruje pojedyncze wiersze.TRUNCATE
generalnie używa mniej blokad, ponieważ wymaga blokady tabeli i blokad strony, w przeciwieństwie doDELETE
blokad wierszy **.IDENTITY
sekwencje:TRUNCATE
resetuje sekwencję tożsamości w tabeli, jeśli jest obecna.(* Zakres = 8 stron.
TRUNCATE
Loguje / usuwa zakresy, jeśli wszystkie są z tej samej tabeli, w przeciwnym razie loguje / usuwa strony z zakresu mieszanego.** Jednym z efektów ubocznych jest to, że
DELETE FROM TABLE
potencjalnie można pozostawić puste strony przydzielone do tabeli, w zależności od tego, czy operacja może uzyskać wyłączną blokadę tabeli, czy nie.)Tak więc (wracając do pierwotnego pytania),
TRUNCATE TABLE
jest zdecydowanie lepszy niżDELETE FROM TABLE
wtedy, gdy opróżniasz tabelę, ale chcesz zachować strukturę (NB:TRUNCATE
nie można jej używać w tabeli, do której odwołuje się klucz obcy z innej tabeli).Jak zauważono w komentarzu @ Tullo, sprawdź również model odzyskiwania bazy danych - jeśli jest pełny, albo zacznij robić kopie zapasowe dziennika, albo zmień model odzyskiwania na prosty. Po wykonaniu którejkolwiek z tych czynności prawdopodobnie będziesz chciał zmniejszyć plik dziennika jako operację jednorazową (Uwaga: tylko plik dziennika ) w celu odzyskania całego wolnego miejsca.
Na koniec jeszcze jedna rzecz, o której należy pamiętać - statystyki tabel. uruchom
UPDATE STATISTICS <TABLENAME>' after
TRUNCATE/
DELETE`, aby optymalizator zapytań nie był wyzwalany przez stare statystyki.źródło
(UWAGA: nie jestem DBA) DELETE jest zarejestrowaną operacją i nie zwalnia zajętego miejsca. Prawdopodobnie masz duży dziennik transakcji zajmujący miejsce i skanowanie tabel uruchomione na „pustym” obszarze tabel. Myślę, że musisz wyczyścić dziennik transakcji i zmniejszyć bazę danych. Ten artykuł StackOverflow powinien zacząć.
I użyj TRUNCATE TABLE, jeśli chcesz to zrobić w przyszłości.
EDYCJA: Moje stwierdzenie o braku rejestrowania TRUNCATE było błędne. oddalony.
źródło