INDEX 從資料存放的角度看索引

2021-09-06 20:07:25 字數 2536 閱讀 2309

測試表結構:

create

table

tb1(

id intidentity(1,1

), c1

int,

c2 int)

1. 聚集索引(clustered index)

聚集索引可以理解為乙個包含表中除索引鍵外多有剩餘列的包含索引,為保證在delete/update操作的正確性,如果聚集索引未宣告為唯一(unique),則系統會聚集索引鍵增加乙個nullable的int型別標識列(uniquifier)以保證記錄唯一性。

唯一聚集索引:

create

unique

clustered

index

idx_id

ontb1

( id

)

非唯一聚集索引:

create

clustered

index

idx_id

ontb1

( id

)

2. 非唯一非聚集索引

為從非聚集索引定位到資料,對於堆表,非聚集索引會存放索引鍵+資料的rid(file_id+page_id+slot_id),對於聚集表,非聚集索引會存放索引鍵+聚集索引鍵。

非聚集索引:

create

index

idx_c1

ontb1

( c1

)

堆表上非聚集索引:

唯一聚集索引表上非聚集索引:

非唯一聚集索引表非聚集索引:

後續的測試預設使用唯一聚集索引

3. 唯一非聚集索引

唯一非聚集索引與非唯一非聚集索引的區別主要在非葉子節點上,唯一非聚集索引的非葉子節點上不會包含rid的資料。

唯一非聚集索引:

create

unique

index

idx_c1_uni

ontb1

( c1

)

4. 包含索引

包含索引在sql server 2008版本中引入,包含列的資料只存在在葉子節點上。包含列不影響索引行的位置(不會被排序),且包含列不會影響索引鍵的大小(sql server 限制索引鍵不得超過900位元組)

create

index

idx_c1_inc_c2

ontb1

( c1

)include

( c2

)

5. 過濾索引

當過濾列不作為索引鍵或包含列時,系統無需在索引中存放過濾列的資料,因此過濾列不會出現在索引的葉子節點和非葉子節點上。

總結&建議:

1. 對於聚集表,由於索引非聚集索引都會包含聚集鍵,因此建議優先考慮靜態+唯一+遞增+長度較小的索引鍵作為索引鍵

a. 靜態:當聚集鍵被更新時,除了將表資料移動到相應的位置上,依次更新所有的非聚集索引,會消耗大量資源,並導致頁拆分和索引碎片

b. 唯一: 非唯一聚集索引增加2至6個位元組的消耗,導致聚集索引和非聚集索引消耗更多頁面

c. 遞增:對於非遞增的聚集索引鍵來說,插入操作會引發頁拆分和索引碎片  

2. 索引列的可選擇性和索引列順:高選擇性不代表該列就適合放在索引前部,還應該考慮針對該列是範圍查詢還是等值查詢,如訂單表的建立時間列createdtime主要用作範圍查詢,而訂單表的產品編號productid主要用等值查詢,那麼對於

where productid=

@p1and createdtime>

@p2and createdtime<

@p3

這樣的查詢,索引 index(productid,createdtime)就會比index(createdtime,productid) 更高效(消耗更少的cpu和io資源)。

3. 索引列順序與統計:索引列先後順序不同,其對於的統計資訊的密度(density)和直方圖(histogram)也不相同,會間接影響到生成的執行計畫。

4. 對於選擇性較低且位於索引列後端的列來說,可以考慮將其放入到包含索引列中。

5. 雖然過濾索引在統計資訊更新方面存在一定的問題,過濾索引依然是解決部分疑難雜症的必殺技(如select top(10) * from orders where productid>10000 order by orderid desc)

6. 在對遞增的列建立索引時,應考慮統計過期導致執行計畫低效的問題,如對訂單表上建立日期列建立索引。

寫得不好,靠妹子加分啦。。

從辯證的角度看產品

從辯證的角度看產品 然而,當我們用我們自身的思維角度去看待一款產品時,往往可能由於對產品接觸的時間太少,或者是使用到功能的不全面,導致我們對一款產品的認識只能達到乙個有限的程度,這往往是不可避免的。同樣的,當我們要去開發一款產品,往往可能由於對產品真正需求的不確定,或者是考慮的不夠周全,導致我們希望...

從彙編的角度看棧

大家都知道,棧區是儲存函式,區域性變數的一塊記憶體區域。那麼讓我們從彙編的角度,來看看函式的執行過程。首先,當我們使用pushl將資料入棧時,棧頂會移動,以容納新增加的值。實際上,我們能不斷將值入棧,棧會在記憶體中保持向下增長,知道存放 或資料的地方。那麼,我們如何知道棧頂位址呢?棧暫存器 esp總...

從oo角度看with的使用

乙個同事維護 delphi 的時候發現原來 的軟體內有很多 with 過多的 with 讓 難以除錯。引入 with 的本意在於節省重複出現的物件名。比如說,如果有這樣的呼叫 function foo begin objecta.prop1 a objecta.prop2 b objecta.run...