開文以前首先要講講幾個概念html
【覆蓋查詢】數據庫
當索引包含查詢引用的全部列時,它一般稱爲「覆蓋查詢」。緩存
【索引覆蓋】網絡
若是返回的數據列就包含於索引的鍵值中,或者包含於索引的鍵值+彙集索引的鍵值中,那麼就不會發生Bookup Lookup,由於找到索引項,就已經找到所需的數據了,沒有必要再到數據行去找了。這種狀況,叫作索引覆蓋;工具
【複合索引】性能
和複合索引相對的就是單一索引了,就是索引只包含一個字段,因此複合索引就是包含兩個或者多個字段的索引;學習
【非鍵列】測試
鍵列就是在索引中所包含的列,固然非鍵列就是該索引以外的列了;優化
下面就開始今天的主題設計
【摘要1】
在 SQL Server 2005 中,能夠經過將非鍵列添加到非彙集索引的葉級別來擴展非彙集索引的功能。經過包含非鍵列,能夠建立覆蓋更多查詢的非彙集索引。這是由於非鍵列具備下列優勢:
* 它們能夠是不容許做爲索引鍵列的數據類型。
* 在計算索引鍵列數或索引鍵大小時,數據庫引擎不考慮它們。
當查詢中的全部列都做爲鍵列或非鍵列包含在索引中時,帶有包含性非鍵列的索引能夠顯著提升查詢性能。這樣能夠實現性能提高,由於查詢優化器能夠在索引中找到全部列值;不訪問表或彙集索引數據,從而減小磁盤 I/O 操做。
說明:第一:只能是針對非彙集索引;第二:比起復合索引是有性能上的提高的,由於索引的大小變小了;
【摘要2】
鍵列存儲在索引的全部級別中,而非鍵列僅存儲在葉級別中。
說明:這就表現爲包含與不包含的關係了。有關索引級別的詳細信息,請參閱表組織和索引組織。
【摘要3】
使用包含性列以免大小限制
能夠將非鍵列包含在非彙集索引中,以免超過當前索引大小的限制(最大鍵列數爲 16,最大索引鍵大小爲 900 字節)。數據庫引擎計算索引鍵列數或索引鍵大小時,不考慮非鍵列。
例如,假設要爲 AdventureWorks 示例數據庫的 Document 表中的如下列創建索引:
Title nvarchar(50)
Revision nchar(5)
FileName nvarchar(400)
由於 nchar 和 nvarchar 數據類型的每一個字符須要 2 個字節,因此包含這三列的索引將超出 900 字節的大小限制 10 個字節 (455 * 2)。使用 CREATE INDEX 語句的 INCLUDE 子句,能夠將索引鍵定義爲 (Title, Revision),將 FileName 定義爲非鍵列。這樣,索引鍵大小將爲 110 個字節 (55 * 2),而且索引仍將包含所需的全部列。下面的語句就建立了這樣的索引。
說明:當你把一個nvarchar(500)的字段設置爲主鍵的時候,你就能夠看到不能超出900字節的提示了。通常來講咱們是不太會作這些操做的,因此那個錯誤提示也是不常見的,也許你可能還見過。
一個數據頁的大小才8k,因此咱們合理的設置每一個字段的大小,不要浪費太多的空間,這樣對查詢也是有好處的,這個include就比較好的的解決了索引和空間的問題,雖然那些include的數據也會佔用空間。
雖然能夠設置include,可是也儘可能不要使用太多的字段做爲索引包含的非鍵列。
【摘要4】
帶有包含性列的索引準則
設計帶有包含性列的非彙集索引時,請考慮下列準則:
* 在 CREATE INDEX 語句的 INCLUDE 子句中定義非鍵列。
* 只能對錶或索引視圖的非彙集索引定義非鍵列。
* 除 text、ntext 和 image 以外,容許全部數據類型。
* 精確或不精確的肯定性計算列均可以是包含性列。有關詳細信息,請參閱爲計算列建立索引。
* 與鍵列同樣,只要容許將計算列數據類型做爲非鍵索引列,從 image、ntext 和 text 數據類型派生的計算列就能夠做爲非鍵(包含性)列。
* 不能同時在 INCLUDE 列表和鍵列列表中指定列名。
* INCLUDE 列表中的列名不能重複。
說明:include不能使用在彙集索引中。後面的兩點,這個在實際中很難想象會有這樣的需求要把重複列放到一個索引中。若是有朋友遇到過這樣的需求能夠告知一些,不勝感激。那若是有是否能夠經過不一樣的列名(其實保存是一樣的值)來解決這個問題呢??
【摘要5】
列大小準則
* 必須至少定義一個鍵列。最大非鍵列數爲 1023 列。也就是最大的表列數減 1。
* 索引鍵列(不包括非鍵)必須遵照現有索引大小的限制(最大鍵列數爲 16,總索引鍵大小爲 900 字節)。
* 全部非鍵列的總大小隻受 INCLUDE 子句中所指定列的大小限制;例如,varchar(max) 列限制爲 2 GB。
說明:varchar(max)這樣的定義是在2005以後纔有的,因此這些數值也是對2005後的版本才生效的。
最大的表列數爲:1024
最大非鍵列數爲:1023
【摘要6】
修改已定義爲包含性列的表列時,要受下列限制:
* 除非先刪除索引,不然沒法從表中刪除非鍵列。
* 除進行下列更改外,不能對非鍵列進行其餘更改:
o 將列的爲空性從 NOT NULL 改成 NULL。
o 增長 varchar、nvarchar 或 varbinary 列的長度。
* 這些列修改限制也適用於索引鍵列。
說明:這些細小的東西一直沒有注意過。因此要記錄下來,用來「防身」,呵呵。
【摘要7】
設計建議
從新設計索引鍵大小較大的非彙集索引,以便只有用於搜索和查找的列爲鍵列。將覆蓋查詢的全部其餘列設置爲包含性非鍵列。這樣,將具備覆蓋查詢所需的全部列,但索引鍵自己較小,並且效率高。
說明:也就是說把經常使用的where後面的條件查詢的字段做爲索引的鍵列,而須要返回的字段就做爲索引包含的非鍵列。
若是where的是兩個或兩個以上的謂詞的話,這個索引就能夠建立爲複合索引了。之前天真的認爲要返回的字段只能經過在複合索引中入這些字段,無論它是否會用來作謂詞。看到這篇文章,纔有了豁然開朗的感受。
【摘要8】
USE AdventureWorks;
GO
CREATE INDEX IX_Address_PostalCode
ON Person.Address (PostalCode)
INCLUDE (AddressLine1, AddressLine2, City, StateProvinceID);
說明:這個是使用include的語法,在表的設計中的索引設計中是沒有辦法選擇的;
【摘要9】
性能注意事項
避免添加沒必要要的列。添加過多的索引列(鍵列或非鍵列)會對性能產生下列影響:
* 一頁上能容納的索引行將更少。這樣會使 I/O 增長並下降緩存效率。
* 須要更多的磁盤空間來存儲索引。特別是,將 varchar(max)、nvarchar(max)、varbinary(max) 或 xml 數據類型添加爲非鍵索引列會顯著增長磁盤空間要求。這是由於列值被複制到了索引葉級別。所以,它們既駐留在索引中,也駐留在基表中。
* 索引維護可能會增長對基礎表或索引視圖執行修改、插入、更新或刪除操做所需的時間。
您應該肯定修改數據時在查詢性能上的提高是否超過了對性能的影響,以及是否須要額外的磁盤空間要求。有關評估查詢性能的詳細信息,請參閱查詢優化。
說明:「這是由於列值被複制到了索引葉級別」這句很好的說明了物理上的存儲結構和原理。
【圖片解析】

上圖也說明了爲何不能在彙集索引中創建具備包含性列的索引,由於非彙集索引的葉層是由索引頁而不是由數據頁組成,這就得說到彙集和非彙集索引的的物理存儲了,彙集索引的順序排序和存儲就是基表的順序和存儲結構。
【一個例子】
SELECT UserName,Password,RealName,Mobile,Age FROM bw_Users WHERE UserName = XXX AND Age = XX
說明:
- 這是一個咱們很常見的查詢語句,咱們如何提升查詢效率呢?
- 首先咱們來看看謂詞,這條語句是經過UserName = XXX AND Age = XX做爲條件的,那麼咱們就應該創建一個組合索引,也稱爲複合索引,注意索引中的鍵列的位置,先UserName後Age;
- 其實上面那個是一個非彙集索引,那咱們就能夠把Password,RealName,Mobile這三列做爲索引包含列;
- 因此,最終就是創建一個以UserName 和 Age作爲鍵列、Password,RealName,Mobile做爲非鍵列的非彙集索引;
- 一般來講咱們系統的用戶表並非很大,因此這樣的優化起不了很明顯的效果,若是有興趣的可使用大表進行性能測試;
【其它】
- 有一點我很奇怪,那就是爲何在修改表的時候,爲何【包含的列】是不可用的?只能經過命令來編寫該類索引?
- 另一點我想說,微軟的MSDN的確是最好的學習工具,在網絡上搜索出來的東西不少都是重複的,並且說的不全,不過能講的比較簡單、通俗而已。因此有空仍是多看看MSDN吧。這句話是對本身說的。呵呵。
http://www.cnblogs.com/gaizai/archive/2010/01/11/1644358.html