SqlServer的性能問題大部分是因為缺少索引或索引不當導致的,因此熟悉掌握索引相關知識是精通SqlServer的第一步。我們可以從索引的數據結構瞭解索引的本質;掌握聚集索引和非聚集索引的區別有助於我們在不同場景下走出誤區、建立合適索引;在一些場景下你也有可能需要用到索引視圖 索引的數據結構 在S ...
SqlServer的性能問題大部分是因為缺少索引或索引不當導致的,因此熟悉掌握索引相關知識是精通SqlServer的第一步。我們可以從索引的數據結構瞭解索引的本質;掌握聚集索引和非聚集索引的區別有助於我們在不同場景下走出誤區、建立合適索引;在一些場景下你也有可能需要用到索引視圖。
索引的數據結構
在SqlServer中,聚集索引和非聚集索引都是以B+樹存儲。一顆m階的B+樹滿足下列條件:
- 樹中每個結點至多有m個孩子。除根結點和葉子結點外,其它每個結點至少有m/2個孩子。根結點至少有兩個孩子。
- 所有葉子結點都位於同一層。
- 有n顆子樹的結點中含有n個關鍵字,每個關鍵字不保存數據,只用來索引,所有數據都保存在葉子結點。葉子結點本身依關鍵字的大小順序鏈接。
二叉查找演算法效率很高,但由於樹的深度過大會導致頻繁的磁碟I/O,影響查詢效率。平衡多路查找樹(B樹)可以大大減少樹的深度,作為索引的數據結構非常適合。
聚集索引的葉子節點存的是數據。
非聚集索引的葉子節點存的是指向堆或聚集索引的指針.
聚集索引、非聚集索引
區別
- 聚集索引存儲的記錄在物理上是連續的,非聚集索引對應的記錄在物理上並不連續。(非聚集索引的鍵值在物理上是連續的)
- 聚集索引一張表只能有一個,非聚集索引有多個
索引列的選擇
- 根據Where條件、Order條件選擇列
- 優先選取選擇性大的列,過濾條件精確的列(“=”要優於”between”)
書簽查找
當使用非聚集索引查找時,如果查詢用到的列不包含在非聚集索引中時,就需要一次書簽查找來檢索其它欄位。書簽查找會產生更多的邏輯讀,當書簽查找次數過多(幾百或幾千),SqlServer會捨棄非聚集索引而使用全表掃描(索引失效),這會導致查詢效率非常低。
包含列
將不在非聚集索引中的列放到包含列中,可以避免書簽查找。相對於聚集索引,由於每頁的數據更多,查詢效率最高。
適用場景
- 需要讀取大量數據時(統計):通常會使用聚集索引。如果查詢用到列總大小遠小於行大小,應選擇非聚集索引+包含列(連續讀的數據量小很多)。
- 不需要讀取大量數據時(分頁查詢):優先使用聚集索引(索引過多會影響更新、刪除性能。)
- 多視角都滿足使用聚集索引的場景時,基於數據量大的查詢建立聚集索引,其它的建立非聚集索引。
註:多視角指的多個維度或方面去查看數據,它們的索引列不同
數據量大小評估需要綜合參考查詢涉及的行數和列的大小
索引視圖
概念
為視圖創建唯一聚集索引可以提高查詢性能,因為視圖在資料庫中的存儲方式與具有聚集索引的表的存儲方式相同。查詢優化器可以使用索引視圖加快查詢速度。優化器使用索引視圖是隱式的,並不需要在查詢中引用該視圖。
創建唯一聚集索引後可以創建更多的非聚集索引。
適用場景
需要創建索引的列分佈在多個表上。
限制
視圖定義中不能包含統計函數(count、distinct、min、max),Outer連接、開窗函數、集合函數(union、except)等。
參考
B樹
http://www.cnblogs.com/tgycoder/p/5077017.html
http://www.cnblogs.com/zhijianliutang/archive/2012/02/03/2337340.html
書簽查找
http://www.cnblogs.com/lzrabbit/archive/2012/05/21/2499389.html
索引視圖
https://msdn.microsoft.com/zh-cn/library/ms191432.aspx