索引列順序選擇

本篇文章也能夠叫作」創建索引時那一列應該放到最前面」。數據庫

    一般對於索引列的選擇的一般準則都是把最高選擇率(譯者注:所謂選擇率指的是在where子句中做爲選擇條件使用次數的比例來講的)的列放在最前面,我接下來並非要說這個準則不對,由於這個準則自己是正確的。但一般在給出這個準則的同時並無同時給出爲何要把最高選擇率的列做爲索引列以及索引列的順序。ide

    綜上緣由,這頗有可能致使對索引列選擇的誤解。好比,在極端狀況下,某我的風聞了上述建議後,把全部非彙集索引的的索引鍵都設置成彙集索引的鍵(由於這列有很高的選擇率),而後開始糾結爲何數據庫的性能開始慘不忍睹。性能

    出現上面那種極端狀況是由於SQL Server爲每個索引存儲統計信息,但這個統計信息僅僅記錄索引索引第一列的統計分佈,這意味着索引僅僅知道第一列的數據分佈,若是第一列不做爲謂詞使用,可能這個索引依然會被使用,但這並非所有。spa

    除了統計分佈圖以外,SQL Server還爲索引列的全部子集存儲密度。對於3列做爲組合索引鍵,SQL Server就會存儲第一列的密度,第一列和第二列的組合密度以及整個三列的組合密度。密度這個詞表示列中所存的數據所不一樣的機率,公式爲1/惟一值。每一個索引上的這個值均可以經過使用DBCC Show_Statistics加上DENSITY_VECTOR選項進行查看。.net

    這也同時意味着,雖然SQL Server知道了第一列的數據分佈,也同時知道索引列中其它鍵組合包含數據的平均值。blog

     那麼,對於索引列的前後順序該怎麼作呢?要把最高選擇率的列放在第一個,剩下的列前後順序就無所謂了。索引

     下面經過下表來看這到底是什麼意思。字符串

CREATE TABLE ConsideringIndexOrder (get

ID INT IDENTITY,it

SomeString VARCHAR (100),

SomeDate DATETIME DEFAULT GETDATE()

);

 

    假設上面的表有10000行,沒有彙集索引因此是基於堆存儲的,而後SomeString列包含100個不一樣的值,SomeDate列包含5000個不一樣的值,而ID列是自增,因此惟一。

    創建一個非彙集索引包含上述散列,順序爲ID,SomeDate,SomeString.

    上面創建的索引只能在謂詞是以下時被使用:

 

WHERE ID = @ID AND SomeDate = @dt AND SomeString = @str

WHERE ID = @ID AND SomeDate = @dt

WHERE ID = @ID

 

    換句話說,這三列的子集只有按從左到右的順序包含在謂詞中才能被where和join使用。

     若是你僅僅在where子句以後使用SomeDate列做爲過濾條件,則不能使用索引進行查找。這就像是你想經過電話本按照人的名字而不是姓查找電話號碼同樣,想找到這我的是不能使用目錄的,而只能翻遍整個電話版。

    此外,把具備最高選擇率的列放在最左邊,但這一列不多在謂詞中使用。而大量的where過濾的是其它列的話,只能進行索引掃描,而掃描的代價很是高。

    由此得出結論如何選擇放在索引第一列的列的標準並不惟一,而是基於數據庫中使用最多的查詢,若是這幾列在where等子句以後使用等於號進行過濾的話,那麼毫無疑問,選擇具備最高選擇率的列放到第一位,這樣SQL Server就有更多的概率知道這個索引有用,若是不是這樣的話,將在where等子句以後使用最多的列放到第一列,這樣這個索引就能夠適用於更多的查詢。

    下面基於文章前面建立的表來作一些查詢。

 

    場景1:用ID做爲謂詞使用等於號進行過濾

    這是最簡單的一個場景,由於這個狀況直接匹配索引的第一列,索引僅僅使用查找方式找到數據。

    

 

    場景2 :  用ID和SomeDate列做爲謂詞使用等於號進行過濾

     這個場景一樣很是簡單,使用和非彙集索引順序相同的子集做爲過濾條件,所以也使用查找方式找到數據。

    

    場景3 :用ID和SomeString列做爲謂詞使用等於號進行過濾

     這個場景就有點意思了。只能使用部分使用ID做爲索引查找條件,由於SomeString列並非索引的第二列。這個索引的第二列是SomeDate但查詢沒有按照SomeDate進行過濾。所以這個查詢首先使用ID進行過濾,而後過濾後的列進行字符串比較來找到匹配的行。雖然這個操做是經過查找實現,但SQL Server僅僅使用查找找到ID,而後再將過濾後的行進行字符串比較。

    

 

    場景4:用SomeDate和SomeString列做爲謂詞使用等於號進行過濾

    在這個場景中,SQL Server就不能使用查找了。索引的第一列並不包含在這個查詢的謂詞以內。只能經過掃描來知足這個查詢。實際上,SQL Server須要將表中這兩列的每一行都和給定值進行比較來找到所需的行。

    

 

    我以爲上述知識已經基本涵蓋了有關索引的等式謂詞。或許我這篇文章讓你更迷惑了。可是至少我但願你更好的瞭解索引以及等號匹配。

相關文章
相關標籤/搜索