覆蓋索引又可以稱為索引覆蓋。
解釋一: 就是select的資料列只用從索引中就能夠取得,不必從資料表中讀取,換句話說查詢列要被所使用的索引覆蓋。
解釋二: 索引是高效找到行的一個方法,當能通過檢索索引就可以讀取想要的資料,那就不需要再到資料表中讀取行了。如果一個索引包含了(或覆蓋了)滿足查詢語句中欄位與條件的資料就叫做覆蓋索引。
解釋三: 是非聚集複合式索引的一種形式,它包括在查詢裡的Select、Join和Where子句用到的所有列(即建立索引的欄位正好是覆蓋查詢語句[select子句]與查詢條件[Where子句]中所涉及的欄位,也即,索引包含了查詢正在尋找的所有資料)。
首先,從叢集索引說起,叢集索引實際上就是一個覆蓋索引,在大多數情況下,可以很直觀地分辨出資料表的當前叢集索引是否有用,因為叢集索引根據索引值欄位控制了資料行的順序。由於SQL SERVER以叢集索引的索引值欄位來排序資料行,所以當你經常需要對某些欄位排序時,把這些要排序的欄位作為叢集索引的索引值,建立叢集索引將對查詢效能會有很大的提升。因為資料已經照叢集索引的索引值欄位的順序排序,所以查詢執行時不需要額外的排序操作。同時如果使用叢集索引來尋找同條記錄的其他欄位的資料,SQL SERVER也不需要額外地通過指標檢索資料,因為在叢集索引找到索引索引值的同時就已經找到整條資料。
叢集索引在檢索符合某個範圍的資料時也很有用。例如,你想要找到所有銷售訂單編號介於18000-19999的訂單,而叢集索引就是通過銷售訂單編號欄位建立的,相近的記錄全部會擺放在一起,則訪問的分頁當然就比較少,通過叢集索引可快速定位包含起始銷售訂單編號的行,然後檢索表中所有連續的行,直到檢索到最後的銷售訂單號。
叢集索引在檢索佔總行數比例很大的資料行時也比較有用。
是使用叢集索引尋找資料的。
使用叢集索引的好處在於:
1)所需要的資料都在子葉層(即資料頁),找到正確的索引索引值後不需要再利用指標做額外的尋找
2)SQL SERVER將符合相同條件的資料集中放在一起
其次,非叢集索引。非叢集索引結構如。
如果想要使建立的非叢集索引同時具備以上兩種好處,那就要建立非聚集覆蓋索引。通過覆蓋索引,所有查詢想要的資料欄位都是索引索引值的一部分,而存放在索引的子葉層級。覆蓋索引不僅僅只包含你寫在WHERE條件內的欄位,而且還包含所有SELECT 需要的欄位,以及在GROUP BY 或ORDER BY 子句內的欄位。
例:
Select <欄位A,B....> from <資料表 T> where <條件欄位C>
在SQL SERVER 2000中我們建立覆蓋索引採用以下方式
Create index idx on T(C,A,B)
建立複合式索引時,欄位的順序很重要,要將條件欄位C放在複合式索引的第一位,把它做為在索引的上層結構的主要排序對象,且僅有它包含統計資料,也就是非子葉層尋找出符合的記錄,然後在存放有其他欄位記錄的子葉層讀取所需要的資料。
但是由於欄位A,B兩列也會在索引的非子葉層出現,除非WHERE條件是多個欄位,或多個欄位排序,否則索引非子葉層放在其他資料欄位用處不大,徒增索引資料量,減低索引效能。
在SQL SERVER 2005可以採用以下方式:
Create index idx on T(C) INCLUDE(A,B...)
為了增強覆蓋索引的功能以提升查詢效率,SQL SERVER 2005 在Create Index語句中提供INCLUDE參數,將與索引值列無關的資料表其他欄位添加到非叢集索引的子葉層,擴充非叢集索引的功能,但這些欄位值不做排序等額外的維護動作。在查詢時僅讀取索引結構就可得到所有相關的資料,不訪問表或叢集索引的資料,從而減少磁碟 I/O 操作,減少讀取資料表本身所花的資源。SQL SERVER 的複合式索引最多隻能有16個欄位,而這些添加到索引子葉層中的相關欄位並不計算在這16個欄位中。
另外,當查詢最佳化程式在該索引中可以發現處理查詢所需要的資料,則雖然複合式索引的第一個欄位不在WHERE條件內,但查詢最佳化程式仍有可能採取適用的複合式索引。或是當查詢語句沒有WHERE條件,但複合式索引覆蓋了所有需要的欄位時,則直接掃描索引的子葉層擷取資料而不是通過掃描資料表尋找資料。
樣本:
create index idx_WBK_PDE_LIST_ORG_HISTROY on [WBK_PDE_LIST_ORG_HISTROY]([WBOOK_NO]) include([QTY_1],[COP_G_NO],[G_NO],[CODE_T],[UNIT_1],[TRADE_TOTAL],[GROSS_WT])
則索引idx_WBK_PDE_LIST_ORG_HISTROY結構中,包含了以WBOOK_NO索引值順序為主要排序對象的上層結構,以及包含資料表內所有WBOOK_NO與[QTY_1],[COP_G_NO],[G_NO],[CODE_T],[UNIT_1],[TRADE_TOTAL],[GROSS_WT]欄位內容的子葉層。如。
接下來我用一個執行個體來解釋一下,中的情況,我們來看看下面這條SQL語句在SQL執行引擎中是如何執行的:
SELECT G_NO, UNIT_1 FROM [WBK_PDE_LIST_ORG_HISTROY] WHERE [COP_G_NO]= 'BENNET'
1) [WBK_PDE_LIST_ORG_HISTROY] 表在[COP_G_NO]列上有一個非叢集索引,因此它尋找非叢集索引的根節點中找出[COP_G_NO]= 'BENNET'的記錄。中1)
2) 從包含[COP_G_NO]= 'BENNET'記錄的索引中間節點中找到指向該記錄的子葉層頁號。中2)
3) 從索引的子葉層中針對每一行資料(假設這裡有100條)擷取書籤(由資料庫物理檔案編號,對應的Page頁碼,對應的行號組成),SQL Server引擎通過書籤尋找從叢集索引或資料表中找出真實的行在對應頁面中的位置。中3)
4) SQL Server引擎從對應的行尋找 G_NO和UNIT_1 列的值。
在上面的步驟中,對[COP_G_NO]= 'BENNET'的所有資料(這裡是100條記錄),SQL Server引擎要搜尋100次叢集索引或資料表以檢索查詢中指定的其它列( G_NO, UNIT_1 )。
如果非叢集索引頁中包括了查詢語句中所需要的資料列(COP_G_NO,G_NO, UNIT_1)的值,SQL Server引擎可能不會執行上面的第3和4步,直接從非叢集索引中尋找[COP_G_NO]列速度還會快一些,直接從索引的子葉層讀取這三列的數值。