1. Index Fragmentation 產生原因
📒前情提要:SQL Server儲存資料的單位為Page(頁面),當建立Index(索引)時,SQL Server預設會在Page填滿資料(FillFactor為0或100),此時如果新增資料時,因為Page已經額滿,所以Index必須使用另一個Page來儲存資料,然而在一連串的異動資料過後,會導致資料散佈在各個Page上,當SQL Server想要讀取Index時,因為資料散佈在Page而使效能低落。
- 在資料庫中,當Index存放資料的Page已經額滿時,若再新增資料就會產生一個新的Page存放資料,而導致Index的資料不連續進而降低Index效能,此時就會產生外部碎裂(External Fragmentation)的問題。
- 在資料庫中,當資料被刪除時,Index存放到Page上的資料也會被刪除,而導致在Page中會有因刪除資料而產生的空間,這些空間會造成Index的資料不連續,此時就會產生內部碎裂(Internal Fragmentation)的問題。
- 看了以上兩個例子可以得知,不論是對資料庫Insert還是Update都有機會產生Index Fragmentation,而一致的原因為 → Index的資料不連續。
2. 該如何做對應的調整?
為了避免索引碎裂發生,我們就必須定時替資料庫健檢,也就是進行索引重組(reorganize)或索引重建(rebuild)。
那麼該如何觀察資料庫中索引的碎裂狀態呢?
你可以透過 SELECT 指令搭配 sys.dm_db_index_physical_stats 這個動態管理函示,將可以查出資料庫中所有索引的碎裂狀態,T-SQL 語法如下:
有了以上的T-SQL 語法可以得到索引碎裂的狀態數據,那麼下一步就是什麼時候適合索引重組、什麼時候適合索引重建呢?
在Microsoft的官方文件中並沒有找到針對重組、重建使用時機相關資訊:
以下的判斷時機參考了不少篇相關資訊並整理在下方:
📒 索引重組的時機
檢查 External fragmentation 部分
-當 avg_fragmentation_in_percent 的值介於 10 到 15 之間
檢查 Internal fragmentation 部分
-當 avg_page_space_used_in_percent 的值介於 60 到 75 之間📌 索引重建的時機
檢查 External fragmentation 部分
-當 avg_fragmentation_in_percent 的值大於 15
檢查 Internal fragmentation 部分
-當 avg_page_space_used_in_percent 的值小於 60參考資訊:https://blog.miniasp.com/post/2009/01/18/Let-SQL-Server-Tell-You-Which-Indexes-to-Rebuild-or-Reorganize
📒 索引重組的時機
檢查 External fragmentation 部分
-當 avg_fragmentation_in_percent 的值介於 10 到 30之間📌 索引重建的時機
檢查 External fragmentation 部分
-當 avg_fragmentation_in_percent 的值大於 30參考資訊:https://solutioncenter.apexsql.com/why-when-and-how-to-rebuild-and-reorganize-sql-server-indexes/
📒 索引重組的時機
檢查 External fragmentation 部分
-當 avg_fragmentation_in_percent 的值介於 5 到 30之間📌 索引重建的時機
檢查 External fragmentation 部分
-當 avg_fragmentation_in_percent 的值大於 30參考資訊:https://www.mssqltips.com/sqlservertip/4470/script-to-manage-sql-server-rebuilds-and-reorganize-for-index-fragmentation/
在找判斷時機的過程中發現其共通點皆是有範圍的做索引重組(reorganize)或索引重建(rebuild),而非全部Index皆執行,可以想像的是,若將全部Index皆做此操作通常會導致資源上的浪費[時間/空間]。
在第二小節我們可以得知為了避免索引碎裂發生,我們就必須定時替資料庫進行索引重組(reorganize)或索引重建(rebuild),然而並非全部Index皆執行,而是有範圍的做索引重組(reorganize)或索引重建(rebuild)。
3. 實際操作
1. 建立一張表 [USERS],欄位[ID]為其Index
2. Insert 100000筆資料刻意產生 Index Fragmentation
3. 使用T-SQL語法自動產出此Index適合索引重組(reorganize)或索引重建(rebuild),此處的參數如下:
📒 索引重組的時機
檢查 External fragmentation 部分
-當 avg_fragmentation_in_percent 的值介於 5 到 30之間📌 索引重建的時機
檢查 External fragmentation 部分
-當 avg_fragmentation_in_percent 的值大於 30
4. 複製自動產出的T-SQL語法 (ALTER INDEX…),並執行
5. 將可以明顯看出[AvgFragmentationPercentage]從 97.94 降為 0
以上就是這次Index Fragmentation的內容啦,聊了產生原因,可以如何做對應的調整,最後Demo一次重建Index,若有問題or錯誤歡迎留言討論!
參考資料:
謝謝你的閱讀!如果有任何回饋或疑問,歡迎留言給我!
如果對我的文章有興趣,請不吝按下Follow & Clap!
每個月都會認真更新文章唷😊 千萬別錯過了~