Sql-Server

聚集索引碎片與包含列碎片的索引

  • December 29, 2020

我有一個相對較大的表(對我來說),有 4000 萬行,預計在兩週內(在活動期間)將增長到 80 到 1.2 億行。

Tip
--------------
Id          int (clustered index)
UserId      int
TipIndex    smallint
Value       binary(8)
LastChanged datetime2(3)
  • 每個使用者都有 1 到 400 個提示,這些提示將在此期間隨機插入
  • UserId + TipIndex 是唯一的
  • 我從不直接在身份密鑰 (Id) 上查詢提示
  • 99% 的時間我都在 UserId 上查詢
  • 我需要所有列
  • 我經常查詢 1 個 UserId(每個頁面視圖),有時會查詢 10.000 個批次的統計資訊
  • 在此期間這是一個高流量站點,它應該能夠每分鐘處理 30.000 次關於 UserId 的查詢
  • Id 目前是我的聚集索引,因為我讀到它導致碎片最少。

所以我在 SQL Azure 上託管,Azure 已經建議添加包含列的索引。我一直對使用 UserId,TipIndex 作為聚集索引猶豫不決,因為提示會隨機添加。這意味著我害怕巨大的碎片問題等。

我的問題:

  • 包含列的索引沒有完全相同的問題嗎?
  • 包含列的表是否與具有相同碎片問題的“影子表”不同?
  • 我是否應該遷移以使用 UserId、TipIndex 作為 ClusteredIndex 而不是 Id?
  • 如何防止碎片化?

我知道最終答案總是“取決於”或者我應該衡量它。但由於我是一個單獨的開發人員,沒有很多資源,我希望有更多經驗的人對此有直覺,所以我的第一次嘗試更有可能朝著正確的方向前進。

看來您太在意碎片了,只要您不斷更新統計資訊,碎片就不應該對性能造成太大影響。您可以在 Brent Ozar 先生分享的影片以及此處的另一個頁面上閱讀有關此的更多詳細資訊。讓我試著一一回答你的問題:

包含列的索引沒有完全相同的問題嗎?

包含列中的索引或者是關鍵列,差別不大。關鍵列將成為 B 樹的一部分,而包含列則不是,但是當您執行任何插入/更新/刪除操作時,這將具有與這些列需要更新/插入/刪除相同的費用。

包含列的表是否與具有相同碎片問題的“影子表”不同?

不太確定影子表是什麼意思,如果你在這裡指的是基表,那麼是的,就碎片而言,你會遇到同樣的問題。

我是否應該遷移以使用 UserId、TipIndex 作為 ClusteredIndex 而不是 Id?

根據您的陳述-“我在 UserId 上查詢的次數有 99%”,這是主鍵聚集列的良好候選者。由於您不會非常頻繁地使用 Id 列,因此我認為使用 UserId 和 TipIndex 形式的複合主聚集鍵沒有任何問題。就索引的大小而言,它與 Id(int –> 4 byte) 加上一個 tinyint 類型的附加列(1 byte) 一樣好。

請理解,集群密鑰只不過是邏輯儲存的數據順序,與非集群密鑰不同,它沒有任何物理存在。

如何防止碎片化?

我想說更新統計資訊應該比碎片化更優先考慮。您可以使用來自 Ola Hallengren 的世界各地許多 DBA 使用的維護腳本。您可以根據您的要求每週或每兩周安排一次。

希望這可以幫助。

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