La "tabella vuota" di SQL Server è lenta dopo aver eliminato tutti (12 milioni) i record?


27

Ho un'istanza di SQL Server 2008 con circa 150 colonne. In precedenza ho popolato questa tabella con circa 12 milioni di voci, ma da allora ho cancellato la tabella in preparazione di un nuovo set di dati.

Tuttavia, i comandi che un tempo correva subito su un tavolo vuoto, come count(*)e select top 1000in SQL Management Studioora prendere eoni per l'esecuzione.

SELECT COUNT(*) FROM TABLE_NAME 

ci sono voluti più di 11 minuti per restituire 0 e SELECT TOP 1000quasi 10 minuti per restituire una tabella vuota.

Ho anche notato che lo spazio libero sul mio disco rigido è letteralmente scomparso (da circa 100G a 20G). L'unica cosa che è successa è stata una singola query che ho eseguito:

DELETE FROM TABLE_NAME

Cosa sta succedendo nel mondo?!?


5
Quale modello di recupero utilizza il tuo database? Se è "Completo", l'istanza di SQL memorizzerà un record di tutte quelle eliminazioni, che potrebbero essere dove è andato lo spazio libero. Se è necessario il ripristino completo, si consiglia di utilizzare TRUNCATE TABLEanziché DELETE FROM.
Tullo_x86

2
150 colonne? Quella tabella potrebbe essere eccessiva - la maggior parte delle tuple dovrebbe essere molto più piccola. Impossibile dirlo senza contesto completo, tuttavia.
Clockwork-Muse

Risposte:


42

Ti è già stato detto perché TRUNCATEsarebbe molto più veloce / migliore / più sexy di DELETE, ma c'è ancora una domanda da affrontare:

Perché è SELECTpiù lento dopo il DELETE completamento ?

Questo perché DELETEha solo fantasma le file. Il tavolo è grande quanto quando aveva 12 milioni di righe, anche se non ne ha. Per contare le righe (0), ci vuole tanto tempo per contare 12M righe. Con il tempo il processo di pulizia dei fantasmi raccoglierà questi documenti fantasma e dislocerà le pagine che contenevano solo fantasmi e i tuoi SELEZIONATI accelereranno. Ma in questo momento se fai il check- Skipped Ghosted Records/secin perfmon probabilmente sta salendo alle stelle durante SELECT COUNT(*). Si potrebbe anche accelerare le cose ricostruendo la tabella: ALTER TABLE ... REBUILD.

TRUNCATE si sarebbe anche preso cura di questo problema, in quanto non lascia indietro fantasmi.

Vedi anche Inside the Storage Engine: pulizia di Ghost in profondità .


13

DELETEle istruzioni eliminano le righe da una tabella una alla volta, registrando ciascuna riga nella transaction loge conservando le log sequence number (LSN)informazioni. Dato che hai menzionato che la tua tabella conteneva enormi dati (12 milioni di record), dopo aver eliminato il tuo disco rigido dallo spazio, controlla la dimensione del file di registro del database. Molto probabilmente sarebbe cresciuto.

un modo migliore sarebbe stato:

TRUNCATE TABLE_NAME

2
+1, esattamente lo stesso vale per Oracle DB. Se si utilizzano istruzioni che causano la registrazione dei record, questo rallenterà il database nel tempo.
Petro Semeniuk

@PetroSemeniuk Da ciò che ricordo su Oracle, delete lascia da solo il segno highwater, truncate ripristinerà il segno highwater. Credo che qualsiasi operazione che richieda una scansione completa scansionerà i blocchi fino al massimo livello dell'acqua. Quindi la cancellazione potrebbe aiutare le operazioni indicizzate, ma non le scansioni. TRUNCATE è stata l'operazione corretta.
Glenn

3

(Questo era originariamente un commento alla risposta di @ DaveE, ma l'ho inserito nella sua risposta perché è diventato lungo)

TRUNCATE è un'operazione registrata. Deve essere altrimenti non conforme ACID. Tuttavia, le differenze tra TRUNCATEe DELETE:

  • Utilizzo dello spazio del registro: TRUNCATEregistra solo le pagine / le estensioni * liberate, mentre DELETEregistra le singole righe.
  • Utilizzo dei TRUNCATEblocchi : generalmente utilizza meno blocchi, poiché richiede un blocco tabella e blocchi pagina, al contrario dei DELETEquali utilizza i blocchi riga **.
  • IDENTITYsequenze: TRUNCATEreimposta la sequenza identità su una tabella, se presente.

(* Un'estensione = 8 pagine. TRUNCATERegistrerà / rimuoverà le estensioni se sono tutte da quella tabella, altrimenti registrerà / rimuoverà le pagine dalle estensioni miste.

** Un effetto collaterale di ciò è che DELETE FROM TABLEpotenzialmente possono lasciare pagine vuote assegnate alla tabella, a seconda che l'operazione possa ottenere o meno un blocco esclusivo della tabella.)

Quindi (tornando alla domanda originale), TRUNCATE TABLEè decisamente meglio che DELETE FROM TABLEse si svuota la tabella ma si desidera mantenere la struttura (NB: TRUNCATEnon può essere utilizzato su una tabella a cui fa riferimento una chiave esterna di un'altra tabella).

Come notato nel commento di @ Tullo, controlla anche il modello di recupero del tuo database - se è pieno, allora devi iniziare a fare i backup del log o cambiare il tuo modello di recupero in semplice. Una volta che hai fatto uno di questi, probabilmente vorrai ridurre il tuo file di registro come un'operazione una tantum (NB: solo file di registro ) per recuperare tutto quello spazio libero.

Infine, un'altra cosa da tenere presente: le statistiche delle tabelle. eseguire UPDATE STATISTICS <TABLENAME>' afterTRUNCATE /DELETE` in modo che l'ottimizzatore della query non venga attivato dalle vecchie statistiche.


2

(NOTA: non sono un DBA) DELETE è un'operazione registrata e non libera lo spazio utilizzato. Probabilmente hai un log delle transazioni di grandi dimensioni che occupa spazio e scansioni di tabelle in esecuzione sul tablespace "vuoto". Immagino che sia necessario cancellare il registro delle transazioni e ridurre il database. Questo articolo StackOverflow dovrebbe iniziare.

E usa TRUNCATE TABLE quando vuoi farlo in futuro.

EDIT: la mia affermazione su TRUNCATE che non è stata registrata era errata. rimosso.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.