[SQL SERVER][Memo]再談 NonClustered Index
上一篇我再度說明建立 Clustered Index 的重要性,而這篇要再來談談NonClustered Index工作方式,
一般來說,一個設計不良的索引通常也會導致查詢效能低落,
而下面我會實際用幾個例子,讓大家知道了解NonClustered Index工作方式重要性,
當然!前提是你想達到架構最佳化或降低查詢成本的話 :) 。
Clustered Index 和 NonClustered Index的差異可以查看我以前文章,這部份我就不討論了。
NonClustered Index工作方式大概分兩種:
1.NonClustered Index包含全部查詢資料:
這時候的 NonClustered Index(涵蓋索引-- cover index) 直接回復查詢,
而避免了Key Lookup(RID Lookup、bookmark lookup)作業運算子,
因為SQL Server不需要額外去存取 data pages中不存在資料行的資料,
建議執行計劃中應該刪除上述提到的邏輯或實體作業運算子。
--假設查詢如下
select [NCALL_HIST_ID_PK]
,[mobile_no]
,[Subscr_id]
,[Sys_id]
,[CCALLER_NAME]
,[DCR_date]
,[User_Code_OTH]
from dbo.[TB_CALL_HIST_TEMP]
where [mobile_no]='0977314481'
我們可以透過以下兩種方法建立相關正確的NonClustered Index(符合查詢)
A.using included column
create nonclustered index nidx_1 on TB_CALL_HIST_TEMP(mobile_no)
include (Subscr_id,Sys_id,CCALLER_NAME,DCR_date,User_Code_OTH)
查詢整體成本:0.00328。
B.using Cover Index
create nonclustered index nidx_2 on TB_CALL_HIST_TEMP
(
mobile_no,Subscr_id,Sys_id,CCALLER_NAME,DCR_date,User_Code_OTH
)
查詢整體成本:0.00328。
雖然方法A和B兩者整體查詢成本都相同,但我個人建議使用A方法,
最主要可以避免索引鍵資料行900 bytes 大小限制。
2.NonClustered Index不包含全部查詢資料:
由於NonClustered Index不包含全部查詢資料,所以SQL Server為了要回覆查詢相關欄位資料,
故需要額外去存取 data page,擷取相關資料行資料並 join 後才返回完整資料行,
這時候你會在執行計畫中看到
Key Lookup(RID Lookup、bookmark lookup)和 Nested Loops (inners Join) 邏輯或實體作業運算子。
錯誤的NonClustered Index(不符合查詢)
create nonclustered index nidx_3 on TB_CALL_HIST_TEMP(mobile_no)
include (CCALLER_NAME,DCR_date,User_Code_OTH)
查詢整體成本:0.00757。
create nonclustered index nidx_4 on TB_CALL_HIST_TEMP(mobile_no)
查詢整體成本:0.00757。
最近某位網友案列: SQL百萬筆資料,使用ROW_NUMBER排序所花時間
結論:
現實世界中的查詢語句往往相當複雜,雖然NonClustered Index建立與否並不會影響 Base Table data,
但你還是要盡量設計並建立最適當的索引類型(Cover Index 並非唯一選擇),
關於索引設計有興趣的朋友可以查看今年4月分我在RUN!PC所發表的資料庫索引概念和設計文章。
參考