2.2、使用窄索引: 為了最好的性能,盡量在索引中使用較少的列。還應當避免寬數據類型的列。 窄索引可以在8KB的索引頁面中容納比寬索引更多的行,可以達到以下效果: l 減少I/O數量(讀取更少的8KB頁面) l 使用數據庫緩存更有效,因為SQLServer可以緩存更少的索引頁面,減少內存中索引頁面所需的邏輯讀操作。 l 減少數據庫存儲空間。
4.1、非聚簇索引維護: 為優化維護開銷,SQLServer添加一個指向舊數據頁的指針,以在頁面分割之后指向新的數據頁面,而不是更新所有相關非聚簇索引的行定位器。將聚簇索引作為行定位器降低了非聚簇索引相關的開銷。 4.2、定義書簽查找: 當查詢請求不是優化器選擇的非聚簇索引一部分時,需要一個查找,這對一個聚簇索引來說是一個關鍵字查找,對堆表來說是一個RID查找。成為:書簽查找。 這種查找根據索引行的行定位器值,從表中讀取對應的數據行,除了索引頁面上的邏輯讀操作以外,還需要一個數據頁面的邏輯讀。但是如果查詢需要列中的索引,那么不需要訪問數據頁面,這種叫做【覆蓋索引】,這些書簽查找是大結果集最好使用聚簇索引的原因。聚簇索引不需要書簽查找,因為葉子頁面和數據頁面相同。 4.3、非聚簇索引建議: 1. 何時使用非聚簇索引: 在需要從一個大表中讀取少量行時最有效。隨著行數增多,書簽查找的開銷成比例增加。索引列應該有很高的選擇性。 有一些索引需求不適合于聚簇索引: l 頻繁更新的列 l 寬關鍵字 2. 何時不使用非聚簇索引: 非聚簇索引不適合檢索大量行的查詢。此時使用聚簇索引更好。因為不需要單獨的書簽查找來檢索數據行。如果需要從表上讀取大量的結果集,那么在過濾和連接條件中的非聚簇索引沒有幫助,除非使用非聚簇索引——覆蓋索引。
五、聚簇索引VS 非聚簇索引
選擇聚簇索引或非聚簇索引主要考慮因素: l 檢索的行數量; l 數據排序需求; l 索引鍵寬度; l 列更新頻度; l 書簽開銷; l 任何磁盤熱點;
5.1、聚簇索引相對非聚簇索引的好處: 在沒有索引的表上選擇索引的類型時,聚簇索引通常是首選。 盡量使用具有高選擇性的列讀取小的結果集是該列上創建非聚簇索引很好的啟示,但在同意列上的聚簇索引可能同樣有利甚至更好。 注意:盡管許多數據檢索中聚簇索引勝過非聚簇索引,但是一個表只有一個聚簇索引,因此,應當將聚簇索引保留在最有力的情況下。 5.2、非聚簇索引相對聚簇索引的好處: 非聚簇索引在以下情況優先于聚簇索引: l 索引鍵尺寸很大。 l 為了避免聚簇索引重建時需要重建所有非聚簇索引的相關開銷。 l 是數據庫讀取程序工作于非聚簇索引頁面上,同時寫入程序對數據頁面中的其他列(不包括非聚簇索引中)進行修改以避免阻塞。 l 當查詢所有引用列(來自一個表)可以安全地容納非聚簇索引中時。 在不需要跳轉到數據行的情況下,非聚簇索引的性能應該和聚簇索引一樣好(甚至更好)。非聚簇索引鍵包含所有表中需要的列是有可能的。
六、高級索引技術
l 覆蓋索引: l 索引交叉:使用多個非聚簇索引以滿足查詢的所有列需求(來自一個表) l 索引連接:使用索引交叉和覆蓋索引技術來避免觸及基本表。 l 過濾索引:為了能夠索引具有零散數據分布的字段或者稀疏的列,可以在索引上應用過濾,這樣它只索引一些數據。 l 索引視圖:在磁盤上將視圖輸出實體化
6.1、覆蓋索引: 在所有為滿足SQL查詢不用到達基礎表所需的列上建立非聚簇索引。如果查詢遇到一個索引并且完全不需要引用底層數據表,那么該索引可以被認為是覆蓋索引。使用INCLUDE操作符使索引編程覆蓋索引,浙江存儲數據和索引而不需要修改索引結構本身。 覆蓋索引本身對于減少邏輯讀是一種游泳的技術。在以下情況使用最好: l 你不希望增加索引鍵的大小,但仍然希望有一個覆蓋索引; l 你打算索引一種不能被索引的數據類型(除了文本、ntext和圖像); l 你已經超過了一個索引的關鍵字列的最大數量(但是最好避免這個問題)。 1、 偽聚簇索引(Pseudoclustered index): 覆蓋索引物理上順序地組織所有索引列。從I/O角度看,沒有使用包含列的覆蓋索引編程一種聚簇索引,用于所有完全滿足于覆蓋索引中列的查詢。如果查詢結果集需要排序,那么覆蓋索引可以用于物理地按照結果集所需的順序維護列數據。 2、 建議: 利用覆蓋索引,要注意SELECT語句中的列清單。應盡可能使用較少的列來保持小的覆蓋索引鍵尺寸。如果索引中所有列的字節數相比表的單個數據行來說較小,而且確定利用覆蓋索引的查詢經常執行,那么覆蓋索引是有效的。 在建立許多覆蓋索引之前,考慮SQLServer如何有效和自動地使用索引交叉為查詢即時創建覆蓋索引。
6.2、索引交叉: 如果一個表有很多索引,那么SQLServer可以使用多個索引來執行一個查詢。根據每個索引選擇小的數據子集,然后執行兩個子集的交叉(即只返回滿足所有條件的那些行) 但在現實世界中,修改現有索引時要考慮以下問題: l 因為各種原因,可能不允許修改現有索引; l 現有非聚簇索引鍵可能已經相當寬; l 使用現有索引的查詢開銷將被這個修改所影響。 為了增進一個查詢的性能,SQLServer可以在表上使用多個索引,因此,考慮創建多個窄索引代替寬的索引鍵。 有時候,可能必須為以下原因創建一個單獨的非聚簇索引: l 重新排列現有索引中的列不被允許; l 覆蓋索引所需要的一些列不能被包含在現有的非聚簇索引中; l 兩個現有非聚簇索引中的總列數可能多余覆蓋索引所需要的列數; 在這些情況下,可以在剩下的列上創建非聚簇索引。
6.4、過濾索引: 是使用過濾器的非聚簇索引,基本上上一個where子句。用倆在可能沒有很好選擇性的一個或多個列上創建一個高選擇性的關鍵字組。對于大量null值時比較適用。 過濾索引在許多方面帶來回報: l 減少索引尺寸從而增進查詢效率。 l 建立更小的索引降低存儲開銷; l 因為尺寸減少,降低了索引維護的成本。 過濾索引需要在訪問或者創建時的一組特殊ANSI設置: ON:ANSI_NULLS,ANSI_PADDING,ANSI_WARNINGS,ARITHABORT,CONCAT_NULL_YIELDS_NULL,QUOTED_IDENTIFIER OFF:NUMERIC_ROUNDABORT
6.5、索引視圖: SQLServer可以在視圖上創建唯一的聚簇索引來磁盤上實體化。這樣的索引成為索引視圖或實體化視圖。在創建以后可以創建非聚簇索引。 1、 好處: l 聚合可以預先計算并被保存在索引視圖中,以在查詢執行期間最小化昂貴的計算; l 表可以預先連接,結果集可以實物化; l 連接或聚合的組成可以被實物化。
2、 開銷: l 基本表中的任何修改必須執行事務的select語句反映到索引視圖中; l 對索引視圖定義的基本表上的任何修改可能發起索引視圖的非聚簇索引中的修改,如果聚簇鍵被更新,聚簇索引也將必須更新; l 索引視圖增加數據庫的維護開銷; l 數據庫中需要更多的存儲; 創建索引視圖包括如下限制: l 視圖的第一個索引必須是唯一聚簇索引。 l 索引視圖上的非聚簇索引只可以在唯一聚簇索引創建之后創建。 l 視圖定義必須是確定性的——即,它對一個給定的查詢只能返回一個可能的結果; l 索引視圖必須只引用相同數據庫中的基本表,而不是其他視圖; l 索引視圖可以包含浮點列但是這樣的列不能包含在聚簇索引鍵中; l 索引視圖必須是綁定到列所引用表的一個架構,以免表架構的修改; l 視圖定義的語法有很多限制 l 必須確定的SET選項列表: ON:ARITHABORT,CONCAT_NULL_YIELDS_NULL,ANSI_NULLS,ANSI_PADDING和ANSI_WARNING OFF:NUMERIC_ROUNDABORT