2009-05-27 13 views
12

Ho una tabella piuttosto grande denominata FTPLog con circa 3 milioni di record Desidero aggiungere un meccanismo di eliminazione per eliminare i vecchi registri ma il comando di cancellazione richiede molto tempo. Ho scoperto che l'eliminazione dell'indice cluster richiede molto tempo.Il comando DELETE è troppo lento in una tabella con indice cluster

DECLARE @MaxFTPLogId as bigint 
SELECT @MaxFTPLogId = Max(FTPLogId) FROM FTPLog WHERE LogTime <= DATEADD(day, -10 , GETDATE()) 
PRINT @MaxFTPLogId 
DELETE FROM FTPLog WHERE FTPLogId <= @MaxFTPLogId 

Voglio sapere come posso migliorare le prestazioni dell'eliminazione?

+0

La colonna FTPLogID è indicizzata? – gbn

+0

Sì, è la chiave primaria – Ahmadreza

+0

Quante righe vengono eliminate e quanto tempo impiega? – Quassnoi

risposta

7

Poiché si tratta di una tabella di registro, non è necessario creare cluster.

È improbabile che lo cerchino su Id.

Modificare il numero PRIMARY KEY in modo che non sia in elenco. Questo userà HEAP metodo di archiviazione che è più veloce sul DML:

ALTER TABLE FTPLog DROP CONSTRAINT Primary_Key_Name 
ALTER TABLE FTPLog ADD CONSTRAINT Primary_Key_Name PRIMARY KEY NONCLUSTERED (FTPLogId) 

, e proprio problema:

SELECT @MaxFTPLogTime = DATEADD(day, -10 , GETDATE()) 
PRINT @MaxFTPLogId 
DELETE FROM FTPLog WHERE LogTime <= @MaxFTPLogTime 
1

controllare la densità della tabella (uso comando DBCC SHOWCONTIG per controllare la densità) densità di scansione [Conteggio migliore: Conteggio effettivo] questo parametro deve essere più vicino al 100% e La frammentazione della scansione logica deve essere più vicina allo 0% per le migliori prestazioni della tabella. In caso contrario, reindicizzare e reindirizzare l'indice di tale tabella per migliorare le prestazioni dell'esecuzione della query.

14

Potrebbe essere lento perché una cancellazione di grandi dimensioni genera un grande registro delle transazioni. Prova a eliminarlo in blocchi, ad esempio:

WHILE 1 = 1 
BEGIN 
    DELETE TOP (256) FROM FTPLog WHERE FTPLogId <= @MaxFTPLogId 
    IF @@ROWCOUNT = 0 
     BREAK 
END 

Questo genera transazioni più piccole. E attenua i problemi di blocco creando spazi di respirazione per altri processi.

È inoltre possibile esaminare partitioned tables. Questi potenzialmente ti permettono di eliminare le vecchie voci facendo cadere un'intera partizione.

+1

L'ho sempre usato quando si eseguono grandi eliminazioni dalle tabelle in cui voglio evitare di bloccarle. Raccomandazione eccellente. – SqlRyan

+1

Utilizzare sempre i batch sempre quando si elimina un sacco di dati. SEMPRE. –

0

Suppongo che non solo questa tabella sia enorme in termini di numero di righe, ma anche che sia molto utilizzata per registrare nuove voci mentre si tenta di pulirla.

Suggerimento di Andomar dovrebbe aiutare, ma vorrei provare a ripulirlo quando non ci sono inserimenti in corso.

Alternativa: quando si scrivono i registri, probabilmente non ci si preoccupa molto dell'isolamento della transazione. Perciò vorrei cambiare il livello di isolamento delle transazioni per il codice/processi che scrivono le voci del registro in modo da può evitare di creare enormi tempdb (a proposito, verificare se tempdb cresce molto durante questo DELETE)

Inoltre, ho pensa che le delezioni dall'indice cluster non dovrebbero essere molto più lente di quelle non in cluster: sei ancora psysically eliminare le righe. Ricostruire questo indice in seguito potrebbe richiedere del tempo.

+0

Sembra che non sia a causa di indice cluster perché ho provato la soluzione di Quassnoi e non ha funzionato. – Ahmadreza

Problemi correlati