[英]Remove records by clustered or non-clustered index
我有一張桌子(比如說ErrorLog
)
CREATE TABLE [dbo].[ErrorLog]
(
[Id] [int] IDENTITY(1,1) NOT NULL,
[Created] [datetime] NOT NULL,
[Message] [varchar](max) NOT NULL,
CONSTRAINT [PK_ErrorLog]
PRIMARY KEY CLUSTERED ([Id] ASC)
)
我想刪除所有早於3個月的記錄。
我在Created
列上有一個非聚集索引(升序)。
我不確定其中哪一種更好(似乎需要同時進行)。
查詢#1 :
DELETE FROM ErrorLog
WHERE Created <= DATEADD(month, - 3, GETDATE())
查詢#2 :
DECLARE @id INT
SELECT @id = max(l.Id)
FROM ErrorLog l
WHERE l.Created <= DATEADD(month, - 3, GETDATE())
DELETE FROM ErrorLog
WHERE Id <= @id
一旦知道了要刪除的最大群集密鑰,那么使用此密鑰肯定會更快。 問題是,是否值得首先使用日期選擇此鍵。 正確的決定取決於表的大小以及需要刪除的數據部分。 表越小,刪除的記錄數也越小,則第一個選項(查詢1)的效率應更高。 但是,如果要刪除的記錄數量足夠大,則“日期”列上的非聚集索引將被忽略,並且SQL Server將開始掃描基表。 在這種情況下,第二個選項(查詢2)可能會更好。 通常還需要考慮其他因素。
我最近解決了類似的問題(從1.5TB表中刪除了約6億(2/3)條舊記錄),最后我決定采用第二種方法。 造成這種情況的原因有很多,但主要有以下幾點。
該表必須可用於新插入,同時刪除舊記錄。 因此,我無法在一個可怕的delete語句中刪除記錄,但是為了避免將鎖升級到表級,我不得不使用幾個較小的批處理。 較小的批次還將事務日志大小保持在合理的范圍內。 此外,我每天只有大約一小時的維護時間,並且不可能在一天內刪除所有必需的記錄。
考慮到上述問題,對我來說,最快的解決方案是根據日期列選擇我需要刪除的最大ID,然后從聚簇索引的開頭開始刪除,直到一個批次接一個批次地刪除所選的ID( 從ErrorLog WITH(PAGLOCK)WHERE ID <= @myMaxId )中刪除TOP(@BatchSize )。 我使用了PAGLOCK提示來增加批處理的大小,而不將鎖升級到表級別。 我每天最后刪除了幾批。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.