譯 索引列,列選擇率和等式謂詞

2022-01-17 06:41:39 字數 2647 閱讀 2284

本篇文章也可以叫做」建立索引時那一列應該放到最前面」。

通常對於索引列的選擇的通常準則都是把最高選擇率(譯者注:所謂選擇率指的是在where子句中作為選擇條件使用次數的比例來說的)的列放在最前面,我接下來並不是要說這個準則不對,因為這個準則本身是正確的。但通常在給出這個準則的同時並沒有同時給出為什麼要把最高選擇率的列作為索引列以及索引列的順序。

綜上原因,這很有可能導致對索引列選擇的誤解。比如,在極端情況下,某個人風聞了上述建議後,把所有非聚集索引的的索引鍵都設定成聚集索引的鍵(因為這列有很高的選擇率),然後開始糾結為什麼資料庫的效能開始慘不忍睹。

出現上面那種極端情況是因為sql server為每乙個索引儲存統計資訊,但這個統計資訊僅僅記錄索引索引第一列的統計分布,這意味著索引僅僅知道第一列的資料分布,如果第一列不作為謂詞使用,可能這個索引依然會被使用,但這並不是全部。

除了統計分布圖之外,sql server還為索引列的所有子集儲存密度。對於3列作為組合索引鍵,sql server就會儲存第一列的密度,第一列和第二列的組合密度以及整個三列的組合密度。密度這個詞表示列中所存的資料所不同的概率,公式為1/唯一值。每個索引上的這個值都可以通過使用dbcc show_statistics加上density_vector選項進行檢視。

這也同時意味著,雖然sql server知道了第一列的資料分布,也同時知道索引列中其它鍵組合包含資料的平均值。

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

下面通過下表來看這究竟是什麼意思。

create

table consideringindexorder (

id int

identity,

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需要將表中這兩列的每一行都和給定值進行比較來找到所需的行。

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

translated by careyson

譯 索引列,列選擇率和等式謂詞

本篇文章也可以叫做 建立索引時那一列應該放到最前面 通常對於索引列的選擇的通常準則都是把最高選擇率 譯者注 所謂選擇率指的是在where子句中作為選擇條件使用次數的比例來說的 的列放在最前面,我接下來並不是要說這個準則不對,因為這個準則本身是正確的。但通常在給出這個準則的同時並沒有同時給出為什麼要把...

選擇率和基數簡析

選擇率和基數簡析 選擇率 selectivity 是乙個介於0和1之間的值,用來表示某個操作所返回的記錄數的比例。乙個操作返回記錄的行數稱作基數 cardinality 基數 選擇率 行數 建立模擬實驗環境 scott prod1 set echo on scott prod1 start tmp ...

索引列的選擇

1.如果對於某個表中的某個字段使用了等式或範圍謂語查詢時,可以考慮將此列做為索引。2.復合索引應該注意引導列的選擇,如果在查詢中,引導列選擇不當,常常查詢時此列經常不做為條件時,那麼這樣就會使得查詢為全表掃瞄 3.有null值的列不宜新增索引,null本無實義,如果將有null列做為索引,那麼在查詢...