聚簇索引和非聚簇索引的乙個標誌性區別就是聚簇索引的葉節點對應著資料頁,從中間級的索引頁的索引行直接對應著資料頁。而非聚簇索引的索引b+樹葉節點不是直接指向資料頁面的。如果表有聚集索引或索引檢視上有聚集索引,則行定位器是行的聚集索引鍵。如果聚集索引不是唯一的索引,sql server 將新增在內部生成的值(稱為唯一值)以使所有重複鍵唯一。此四位元組的值對於使用者不可見。僅當需要使聚集鍵唯一以用於非聚集索引中時,才新增該值。sql server 通過使用儲存在非聚集索引的葉行內的聚集索引鍵搜尋聚集索引來檢索資料行。
接下來對上面建立的表進行查詢,select * from tb_index_test where it_smallint_test=20,通過i/o分析得知,這一條查詢語句是通過index scan進行掃瞄。邏輯i/o讀取次數為433次。對it_smallint_test列建立非聚簇索引後,在進行查詢。通過i/o分析得知,在建立非聚簇索引之後,這一條查詢語句還是通過index scan進行查詢,邏輯i/o讀取次數為還是為433次。將之前建立的非聚簇索引刪除掉,對it_smallint_test建立聚簇索引。再進行查詢,可以發現這時是採用index seek進行查詢。
聚簇索引原因分析:使用sql server的dbcc指令進行分析。在建立聚簇索引的情況下,執行下面的指令獲取資料表的頁分配資訊。
在執行之後只要關注pagetype列,pagetype列為2的是表示該資料頁是索引頁面。pagetype為2的資料行有以下這三個。 pagepid indexid pagetype indexlevel nextpagepid prevpagepid
214 1 2 2 0 0
1600 1 2 1 1664 0
1664 1 2 1 0 1664
對資料也214執行sql server的檢視頁資訊的指令。
可以得到下面的資訊:
因此可以得知:214這個資料頁是聚簇索引b+樹的根,其下面有兩個子節點:1600,1664。接下來再對1600這個資料也執行資料頁檢視指令。得到下面的資訊:
注意紅色箭頭的這兩個列,乙個是我們建立的索引列的值,乙個是這個值對應的資料頁面。也就是it_smalint_test的值為1對應的資料也是1377,1378,1379,1380,這四個資料頁。在執行查詢it_smalint_test的值為1是,通過通過索引的查詢直接去讀取這四個資料頁面。因此邏輯i/o次數比較少,查詢效率比較高。
非聚簇索引的原因分析:
將聚簇索引刪除, 對it_smalint_test建立非聚簇索引。還是執行檢視指令,這是會很意外的發現pagetype為2的資料頁好多,而且indexlevel為1的值有乙個,其他都是indexlevel為0的資料頁。對indexlevel等於1的資料頁也執行資料頁檢視指令。可以得到下面的資訊:
這是的childpageid對應的是pagetype=2,並且indexlevel=0的資料頁,可以得知這時的非聚簇索引的b+樹深度為1,只有乙個根節點,有200個子節點。it_small_test的值是從1到100,每個值占用兩個資料節點,即兩個資料頁(其實這樣的看法是錯誤的1035這個索引資料頁也有存放it_small_test=3的rid,這個b+樹的查詢演算法有關)。 接下來執行資料頁檢視指令,檢視pageid=1037這個資料頁,可以得到以下資訊。
heap rid就是對於的資料列的rowid,這個是有檔案id,資料頁id組成,這是資料行的唯一標識。這就是非聚簇索引的特點,b+樹葉子節點存放這rowid。因此在查詢it_small_test=3時,是通過查詢索引樹找到rid,然後再去資料表的堆上去查詢的資料行,注意這時是一行一行去查詢的,而不是乙個資料頁乙個資料頁去查詢的,和聚簇索引查詢的情況是不一樣的。這樣的查詢效率顯然是低的,因為需要先去查詢索引樹,接下來再去遍歷分配資料表的堆上面查詢資料,這樣還不如直接使用index scan掃面快,於是查詢分析器自動選擇index scan,其實繞了一大圈就是得出乙個結論:在某乙個資料列的取值分布在乙個很小的區間(相對於資料總量),並且資料重複出現的頻率高的情況下。像上面的資料表,使用非聚簇索引效率不高。使用聚簇索引熊侶比較高。
另外的乙個結論:在查詢條件的between的時候,或者是大於某個值,小於某個值的時候,使用聚簇索引的效率比使用非聚簇索引效率高。
這些結論還可能會有bug,在資料量是100w的情況下呢? 這裡的答案是:非聚簇索引同樣不適用,歸結為乙個原因:在返回大資料結果集的情況下是不適合使用非聚簇索引的。
參考文章:
非聚簇索引結構
聚簇索引結構
索引設計指南: 索引設計基礎知識
非聚簇索引設計指南
聚簇索引設計指南
聚簇索引和非聚簇索引
一 聚簇索引 clustered indexes 的使用 聚簇索引是一種對磁碟上實際資料重新組織以按指定的乙個或多個列的值排序。由於聚簇索引的索引頁面指標指向資料頁面,所以使用聚簇索引查詢資料幾 乎總是比使用非聚簇索引快。每張表只能建乙個聚簇索引,並且建聚簇索引需要至少相當該錶120 的附加空間,以...
聚簇索引和非聚簇索引
一 聚簇索引 clustered indexes 的使用 聚簇索引是一種對磁碟上實際資料重新組織以按指定的乙個或多個列的值排序。由於聚簇索引的索引頁面指標指向資料頁面,所以使用聚簇索引查詢資料幾乎總是比使用非聚簇索引快。每張表只能建乙個聚簇索引,並且建聚簇索引需要至少相當該錶120 的附加空間,以存...
聚簇索引和非聚簇索引
一 聚簇索引 clustered indexes 的使用 聚簇索引是一種對磁碟上實際資料重新組織以按指定的乙個或多個列的值排序。由於聚簇索引的索引頁面指標指向資料頁面,所以使用聚簇索引查詢資料幾 乎總是比使用非聚簇索引快。每張表只能建乙個聚簇索引,並且建聚簇索引需要至少相當該錶120 的附加空間,以...