2016年11月13日 星期日

索引建立時,將欄位放在key中跟用include涵蓋進來有什麼差異?


這個題目,舉個例子來說
假設有一句select語法如下:
select t2,t3,t4 from testtable where t2=15189 and t3=2
我們如果要針對這句SQL,建立一個適配的index,有下列兩種建法,都可以做到全涵蓋:
1create index idx1 on testtable(t2,t3,t4)
2create index idx1 on testtable(t2,t3) include(t4)
(當然clustered index也可以做到全涵蓋,它有點類似於(1),此篇僅先探討這兩種index對上述SQL的優劣分析)

在兩者的使用時機上,國外網友的文章已經說的很清楚了。以上述的SQL語法,這位作者是建議使用(2)的方法,在這裡就不在多說了。


在此我想從內部的結構面做個闡述:

首先,只有key columns會被放在根頁面及中繼頁面之中。include的欄位值,只存在於「分葉層頁面」,在根頁面及中繼頁面是不會把include欄位值放進來的,因為include欄位並不用於搜尋。所以include的做法,可以節省根頁面及中繼頁面的數量(因為key欄位變少了)
在分葉層頁面中呢,則不論是keys columns include columns都會被存放在分葉層頁面裏。
從分葉層頁面(leaf page)來講,這兩者兩者佔用的空間是一樣的。
從非分葉層頁面(root/intermediate page)來看,上面的2使用include,它的index row會比較短,因此會降低中繼頁面的數量,從這個角度上來講2優於1)。

第二點,當把key放在 key-columns裏面時,在根頁面及中繼頁面中它必需是排序的,如1的索引,就會依t2,t3,t4的順序下去排序。而當t4放在include中,則只會依t2,t3排序,t4就如同heap不會排序(如下圖的index-paget2=15178,可以看到t4沒有排序,當新增時,如果t2,t3相同,資料永遠會被加在倒數第二筆)















12的差別在於include的欄位不加入排序(亦即無法當作搜尋欄位),它的好處是,新增資料時,速度會比keys欄位的index要快,因為它可以少一次的排序重組動作。如果是keys欄位,則三個欄位都必需按順序來排,當新增或異動資料時速度較慢。
再畫個圖來說明:


有兩個index
idx1key只有一個id,其它兩個name,cityinclude columns

idx2key包含了id,name,city,沒有include


這時候,如果再新增一筆「10001AlanNY」的資料進來,該如何存放




由於idx1,只用idkey,所以它不用考慮name,city的排序,但idx2是用3個欄位當key,所以它需考慮name,city的排序,因為idx2在新增資料的時候,會比較慢。(如果有updatekey值,也是一樣需要考慮排序)。因此從這點來看2同樣優於1


2 則留言:

  1. 想知道如果一個資料表有 n 個欄位,但不同的查詢需要 select 不同的欄位,但條件式都是 where t2=xxx and t3=ooo
    那麼若是建立成 include 全部欄位,跟 include 會被 select 的欄位,二者的效能會有什麼差異呢?

    回覆刪除