SQL Server 索引碎片產生原理重建索引和重新組織索引
數據庫存儲本身是無序的,建立了聚集索引,會按照聚集索引物理順序存入硬盤。既鍵值的邏輯順序決定了表中相應行的物理順序
多數情況下,數據庫讀取頻率遠高於寫入頻率,索引的存在 為了讀取速度犧牲寫入速度
頁 為最小單位 8kb
區 物理連續的頁(8頁)的集合
內部碎片 數據庫頁內部產生的碎片,外部反之
碎片的產生:
有一個表裏有8條數據,已經將一頁填滿,這個時候要插入第九條數據,頁也就分裂了。這就產生了內部碎片。如下圖所示(excel示意一下 懶癌晚期)
註: 不會將9單獨分到第二頁,索引B+樹存儲,會讓存儲盡量平衡,以減少檢索層級。
且一般情況下SQL Server數據庫默認設置有20%的填充因子
另外,在插入1~8之後 9之前,很可能數據庫在這段時間有N多新增數據,也就是在物理結構上 頁1 和 頁2 無法連續。這就無法避免的產生了外部碎片。
查看碎片情況:
用到這個極重要的 sys.dm_db_index_physical_stats 動態函數,傳聞數據庫引擎在思考自己如何高效的查詢數據的時候都要來這瞅瞅。
太高深的我並不會,目前我就看以下幾個,其他參照MSDN
avg_fragmentation_in_percent =>當前索引碎片百分比 【如果碎片小於10%~20%,碎片不太可能會成為問題,如果索引碎片在20%~40%,碎片可能成為問題,但是可以通過索引重組來消除索引解決,大規模的碎片(當碎片大於40%),可能要求索引重建。】
avg_page_space_used_in_percent =>所有頁中使用的可用數據存儲空間的平均百分比
page_count =>索引或數據頁的總數
select * from sys.dm_db_index_physical_stats(DB_ID() ,object_id(‘agent‘) ,NULL,NULL,NULL)
碎片的解決:
1.刪除索引並重建
這種方式有如下缺點:
索引不可用:在刪除索引期間,索引不可用。
阻塞:卸載並重建索引會阻塞表上所有的其他請求,也可能被其他請求所阻塞。
對於刪除聚集索引,則會導致對應的非聚集索引重建兩次(刪除時重建,建立時再重建,因為非聚集索引中有指向聚集索引的指針)。
唯一性約束:用於定義主鍵或者唯一性約束的索引不能使用DROP INDEX語句刪除。而且,唯一性約束和主鍵都可能被外鍵約束引用。在主鍵卸載之前,所有引用該主鍵的外鍵必須首先被刪除。盡管可以這麽做,但這是一種冒險而且費時的碎片整理方法。
基於以上原因,不建議在生產數據庫,尤其是非空閑時間不建議采用這種技術。
2.使用DROP_EXISTING語句重建索引
為了避免重建兩次索引,使用DROP_EXISTING語句重建索引,因為這個語句是原子性的,不會導致非聚集索引重建兩次,但同樣的,這種方式也會造成阻塞。
CREATE UNIQUE CLUSTERED INDEX IX_C1 ON t1(c1) WITH (DROP_EXISTING = ON)
缺點:
阻塞:與卸載重建方法類似,這種技術也導致並面臨來自其他訪問該表(或該表的索引)的查詢的阻塞問題。
使用約束的索引:與卸載重建不同,具有DROP_EXISTING子句的CREATE INDEX語句可以用於重新創建使用約束的索引。如果該約束是一個主鍵或與外鍵相關的唯一性約束,在CREATE語句中不能包含UNIQUE。
具有多個碎片化的索引的表:隨著表數據產生碎片,索引常常也碎片化。如果使用這種碎片整理技術,表上所有索引都必須單獨確認和重建。
3.使用ALTER INDEX REBUILD語句重建索引
使用這個語句同樣也是重建索引,但是通過動態重建索引而不需要卸載並重建索引.是優於前兩種方法的,但依舊會造成阻塞。可以通過ONLINE關鍵字減少鎖,但會造成重建時間加長。
阻塞:這個依然有阻塞問題。
事務回滾:ALTER INDEX REBUILD完全是一個原子操作,如果它在結束前停止,所有到那時為止進行的碎片整理操作都將丟失,可以通過ONLINE關鍵字減少鎖,但會造成重建時間加長。
4.使用ALTER INDEX REORGANIZE
這種方式不會重建索引,也不會生成新的頁,僅僅是整理葉級數據,不涉及非葉級,當遇到加鎖的頁時跳過,所以不會造成阻塞。但同時,整理效果會差於前三種。
4種索引整理技術比較:
特性/問題 | 卸載並重建索引 | DROP_EXISTING | ALTER INDEX REBUILD | ALTER INDEX REORGANIZE |
在聚集索引碎片整理時,重建非聚集索引 | 兩次 | 無 | 無 | 無 |
丟失索引 | 是 | 無 | 無 | 無 |
整理具有約束的索引的碎片 | 高度復雜 | 復雜性適中 | 簡單 | 簡單 |
同時進行多個索引的碎片整理 | 否 | 否 | 是 | 是 |
並發性 | 低 | 低 | 中等,取決於冰法用戶活動 | 高 |
中途撤銷 | 因為不使用事務,存在危險 | 進程丟失 | 進程丟失 | 進程被保留 |
碎片整理程度 | 高 | 高 | 高 | 中到低 |
應用新的填充因子 | 是 | 是 | 是 | 否 |
更新統計 | 是 | 是 | 是 | 否 |
參考: SQL Server索引的維護 - 索引碎片、填充因子 <第三篇>
msdn sys.dm_db_index_physical_stats (Transact-SQL)
SQL Server 索引碎片產生原理重建索引和重新組織索引