Sql-Server

配置和維護具有許多平均空的插入和刪除的表的最佳方法?

  • July 15, 2019

存在一個“批量查詢”表,它有兩列(BatchID、RecordID),它們都是 TSQL 類型的“唯一標識符”。唯一的聚群鍵在(BatchID,RecordID)上,並且沒有二級索引。

我們使用 SqlBulkCopy 將數千或數百萬個 id 快速插入到單個批處理 id 下的表中,以便各種查詢可以對其進行連接,以使用與該批處理關聯的記錄 id 集執行過濾。這種方法比嘗試在查詢字元串中發送所有 id 列表的多個查詢要快得多。一旦查詢完成,這批記錄 id 就會被刪除。當沒有查詢執行時,該表平均為空,但可能有數百個活動批次,因為我們每秒處理數千個可能使用該表的 API 請求。

我的問題是,如果有的話,DBA 需要什麼樣的維護步驟來維護這些表。例如,它是否會從定期索引重建中受益,或者 SQL Server 是否會自行處理已刪除行的清理(釋放頁面塊等)。此外,是否有任何特殊的表或聚集索引配置會有所幫助,特別是考慮到標識符是隨機 Guid(唯一標識符)。

一般我們使用最新版本的SQL Server,企業版。有些伺服器在 Azure 中,有些在 AWS 中。

我也有興趣聽到替代方案。例如,我假設這種方法最適合永久表,但我也可以創建一個會話本地臨時表作為事務的一部分,該表在完成時被刪除,而不是從永久表中插入和刪除行。我只是不知道相比之下會如何。

根據我使用 SQL Server 2016 企業版的經驗,在類似的過程中使用永久表作為消息隊列 - 因此它具有非常高的插入和刪除率 - 我們發現每 5 到 10 分鐘重建一次索引有利於強制刪除記錄清理。這極大地提高了表的讀取性能。

在我們的例子中,數據庫隔離級別是讀取送出的快照,出列/刪除過程刪除記錄的速度比幽靈清理過程清除記錄的速度要快。對於高重影記錄數,選擇一條記錄有時需要 1-3 秒而不是 5-10 毫秒,因為 SQL 必須讀取所有重影記錄,這由高掃描計數(帶有set statistics io on)表示。

檢查幽靈記錄的數量:

SELECT version_ghost_record_count, * 
FROM sys.dm_db_index_physical_stats(DB_ID(), OBJECT_ID('[transport].[BatchTable]'), NULL, NULL, 'SAMPLED')

https://docs.microsoft.com/en-us/sql/relational-databases/ghost-record-cleanup-process-guide?view=sql-server-2017#ghost-record-cleanup-task

幽靈清理過程會按一定時間間隔自動執行(SQL Server 2012+ 每 5 秒一次,SQL Server 2008/2008R2 每 10 秒一次)並檢查是否有任何頁面被標記了幽靈記錄。如果找到任何內容,它就會刪除標記為刪除或重影的記錄,每次執行最多觸及 10 頁。

在具有許多刪除的高負載系統上,ghost 清理過程可能會導致性能問題,因為將頁面保留在緩衝池中並生成 IO

我認為“最多 10 頁”部分是我們的限制因素,因為高刪除率超過了清理過程每次執行可能觸及的頁面數量。

引用自:https://dba.stackexchange.com/questions/241805