2011-03-10 19 views
2

我有這個函數,刪除了不再從大表需要用超過10萬行如何從SQL Server中的大量表中刪除時減少事務日誌使用情況?

DELETE FROM BigTable 
WHERE DATEDIFF(month,dtmtimestamp, getdate()) > 2) 

那麼這個方法我試過,以減少使用的事務日誌的空間量的歷史數據:

WHILE (SELECT COUNT(*) FROM BigTable WHERE DATEDIFF(month,dtmtimestamp, getdate()) > 2) > 0 BEGIN 
    DELETE TOP 10000 FROM BigTable 
    FROM BigTable 
    WHERE DateDiff(month,dtmtimestamp, getdate()) > 2 
CONTINUE END 

這是正確的方法嗎?或者我會用這種方式使用更多的事務日誌?

這個好方法的任何提示?

乾杯,
尼科

最終答案

DECLARE @Remainder INT 
DECLARE @ChunkSize INT 
SET @Remainder = (SELECT COUNT(id) FROM BigTable WHERE dtmtimestamp < DateAdd(month, -2, getdate())) 
SET @ChunkSize = CEILING(@Remainder/100) /* Divide the total into 100 parts, whole integers only */ 
WHILE @Remainder BEGIN 
    BEGIN TRANSACTION deletehistorical 
    DELETE TOP (@ChunkSize) 
    FROM BigTable 
    WHERE dtmtimestamp < DateAdd(month, -2, getdate()); 
    SET @Remainder = @@ROWCOUNT; 
    COMMIT TRANSACTION deletehistorical 
END 

checkpoint命令只告訴引擎從日誌(簡單恢復模式)刪除完成的事務,併爲這個查詢實際上仍然繼續每個循環交易仍在創建。因此,爲了分解事務,我添加了一個BEGIN和COMMIT來強制數據庫每次都進行這些更改。

回答

4

而不是計算行數還是刪除,你應該要麼使用EXISTS(只要它找到一個排的話,它返回):

WHILE EXISTS(SELECT * FROM BigTable WHERE DATEDIFF(month,dtmtimestamp, getdate()) > 2) BEGIN 

或者sneakier:

select top 1 * from sysobjects /* Force @@ROWCOUNT > 0 */ 
WHILE @@ROWCOUNT BEGIN 
    DELETE TOP 10000 FROM BigTable 
    FROM BigTable 
    WHERE dtmtimestamp< DateAdd(month, -2,getdate()) 
CONTINUE END 

表中唯一的搜索是用於實際刪除的表。

我也移動了你的日期邏輯,以防dtmtimestamp列有一個有用的索引。

編輯當然,正如馬丁指出的,這些地址都不涉及事務日誌的使用。

限制刪除的策略是合理的,可以阻止可怕的日誌使用,但需要同時發生大量的日誌備份或截斷,以允許重新使用舊的事務日誌空間。否則,它仍然會增長日誌。

如果您知道日誌備份正在發生,比如說每隔15分鐘,您可能希望每隔n次迭代一次,並使用WAITFOR DELAY暫停循環,以便您知道以前的事務日誌使用情況已備份/清除。無論發生什麼,只要您刪除而不是截斷,每個刪除行的日誌記錄仍將佔用日誌或日誌備份中的空間。

如果您能夠脫機正常使用此係統,並且想要保留的行數量大大超出要刪除的行數,您可能需要複製行以保留到另一個表中,刪除所有外鍵,截斷表,將保留的行復制回來,然後重新生成外鍵。因人而異。

+0

+1刪除我的評論,因爲我們都有同樣的想法! – 2011-03-10 15:24:04

+0

好的,現在計劃使用偷偷摸摸的方法。 我正在使用簡單的恢復模式,所以沒有備份正在完成,但我想通過數千次刪除進行計費會在事務日誌中創建大量內容,並且需要有時自行清除。所以也許WAITFOR DELAY會解決這個問題。 – NikoRoberts 2011-03-10 19:37:10

+0

我有一個問題。我只看到只爲一個表刪除很多行的示例。如果我需要從數據庫中刪除數百萬條記錄,那麼該怎麼辦?這個「10000」方法是否有效?或者我需要單獨嗎? – jpgrassi 2014-05-05 12:42:44

1

將恢復模式更改爲簡單的數據庫,進行更新/刪除,然後切換回上一個恢復模式。

+0

這個數據庫的正常恢復模式已經很簡單了,但是在刪除幾百萬行時仍然會消耗掉250GB:/ How,我還不確定 – NikoRoberts 2011-03-10 17:22:00

1

由於數據庫處於簡單恢復,讓您的腳本問題每第N次迭代後

CHECKPOINT 1;

命令,以釋放日誌。

0

在簡單恢復模式下,如果日誌變滿70%,則會自動檢查點排隊。 限制db屬性中的最大日誌文件大小將防止日誌文件超出界限。

相關問題