2009-05-27 63 views
12

我有一個名爲FTPLog的大表,裏面大約有3千萬條記錄我想添加刪除機制來刪除舊日誌,但刪除命令需要很長時間。我發現刪除聚集索引需要很長時間。DELETE命令在帶聚簇索引的表中速度太慢

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

我想知道如何提高刪除性能?

+0

是否將FTPLogID列編入索引? – gbn 2009-05-27 08:45:18

+0

是的,它是主鍵 – Ahmadreza 2009-05-27 09:22:03

+0

刪除了多少行,需要多長時間? – Quassnoi 2009-05-27 10:05:49

回答

7

由於它是一個日誌表,因此不需要進行聚類。

您不可能在Id上搜索它。

改變你的PRIMARY KEY,使它不被聚合。這將使用HEAP存儲方法是在DML更快:

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

,只是問題:

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

檢查表的密度(使用命令DBCC SHOWCONTIG檢查密度) 掃描密度[最佳計數:實際計數]此參數應接近100%,並且邏輯掃描碎片參數應接近0%以獲得最佳表格性能。如果不是,則重新索引並對該表的索引進行重新分片,以提高查詢執行的性能。

14

它可能很慢,因爲大的刪除會生成大的事務日誌。嘗試將其以塊刪除,例如:

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

這會生成較小的事務。它通過爲其他流程創建呼吸空間來緩解鎖定問題。

您可能還會考慮partitioned tables。這些可能允許您通過刪除整個分區來清除舊條目。

0

我認爲這個表格不僅在行數方面很大,而且在你嘗試清理它時記錄新條目的確很重要。

Andomar的建議應該有所幫助,但是我會嘗試在沒有插入時進行清理。

備選方案:當您編寫日誌時,您可能並不關心事務隔離這麼多。因此,我會改變事務隔離級別爲寫日誌條目代碼/流程,讓您可能避免創造出巨大tempdb(順便說一下,檢查是否tempdb數據庫在此DELETE操作增長了不少)

另外,我認爲聚集索引中的刪除不應該比非聚集索引中的真正慢,因爲您仍然在刪除行。之後重建此索引可能需要一些時間。