簡體   English   中英

通過聚集或非聚集索引刪除記錄

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM