Sql-Server

SQL Server 聚集索引高碎片

  • May 24, 2013

我有一個以整數(4 字節)作為主鍵的表。它被定義為一個身份。它也是聚集索引。

外掛工作得很好。插入 2000 行後,碎片率約為 4%。

但是,每條記錄之後將至少更新 3 次。這會生成超過 99% 的此聚集索引的碎片(使用預設填充因子)。

或使用我測試的其他填充因子: - 將聚集索引的填充因子設置為 80(碎片 > 98%) - 將聚集索引的填充因子設置為 50(碎片 > 94%)

所以這看起來不會有很大幫助……

我在一個新創建的表上測試了每個填充因子設置,其中包含 2000 次插入(以及 3 次以上更新)

沒有選擇或更新不包括查詢中的主鍵。

有誰知道為什麼這個索引有這麼高的碎片?

通過 ADO.NET 進行更新,這是生成的命令(由 SQL Profiler 跟踪):

exec sp_executesql N'UPDATE MyTable SET MyValue = @MyValue WHERE MyId = @MyId',
N'@MyValue varchar(50),@MyId int',@MyValue='This is some random value',@MyId=1234

其他更新遵循相同的模式(更新其他值,但始終提供 @MyId 參數)

謝謝您的幫助 :)

FILLFACTOR僅在您建構或重建索引時適用,而不是在正常操作期間。正常操作總是嘗試將頁面填充到 100%。

如果插入具有可變寬度的行,然後將該行更新為更長,如果沒有足夠的額外空間在同一頁面上儲存殘像,則該行將不再適合頁面。如果沒有足夠的空間,這將導致頁面拆分,這是創建必要空間的過程。

頁面拆分有點讓人誤解的是,有“好的拆分”和“壞的拆分”,即使性能計數器計算了所有這些

  • 一個好的拆分是將新行添加到索引的末尾,就像您執行初始批次INSERTs 時發生的情況一樣。新行不適合最後一頁,因此儲存引擎必須分配一個新頁並在邏輯上將其連接到最後一個索引頁。新頁面可能會在舊的最後一個索引頁面之後物理存在。
  • 錯誤的拆分是指必須在索引中間插入一個頁面:新頁面在邏輯上附加到索引結構的兩側,但可能(很可能)不以與這些頁面連續的物理順序存在。

碎片是邏輯順序和物理順序之間的差異,並且在大多數情況下,只有不良類型的頁面拆分會導致碎片。

因為您正在誇大已經存在的行的大小,這會導致頁面拆分的錯誤類型,這就是您看到高碎片數的原因。

目前尚不清楚您的確切過程是什麼,以及最終將在此表中結束多少行。如果它類似於一次性填充,請執行完整填充過程,然後轉身並使用 100% 重建聚集索引FILLFACTOR

如果此過程連續發生,您可以通過執行以下操作“預分配”空間:向表中添加一個虛擬可變寬度列,將其填充為 上的最大長度INSERT,然後在第一個上UPDATE,將虛擬值設置為NULL同時更新實際值。由於所有數據值四處飛散,此方法可能會增加日誌記錄機制的成本。

不過,一般來說,當所有這些因素都成立時,您只需要關注碎片化:

  • 索引足夠大,隨機讀取頁面(範圍)太慢(選擇您自己對“太慢”的定義)
  • 將掃描索引
  • 索引頁(範圍)將從磁碟物理讀取(即,它們尚未在緩衝池中)
  • 儲存子系統在處理隨機讀取方面很差(即基於主軸的,並且字節不會從記憶體中出來)

但是,我建議採用可靠的索引維護解決方案,以或多或少地控制事情。您可以搜尋此站點以獲取有關此的建議。

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