說說複合索引html
寫索引的博客太多了,一直不想動手寫,有一下兩個緣由:
一是以爲有炒剩飯的嫌疑,有兄弟曾說:索引嗎,只要在查詢條件上建索引就好了,真的能夠這麼暴力嗎?
二來以爲,索引是個很是大的話題,很難歸納出全部的狀況,你不整出點新意來,卻是有抄襲照搬的嫌疑post
既然寫了,就寫一點稍微不同的東西出來,
好了,廢話打住,開搞測試
/*this
20160814備註:今天發現一個相似的文章:http://www.cnblogs.com/fly_zj/archive/2012/08/11/2633629.html ;url
能夠理解爲:添加組合索引時,作相等運算字段應該放在最前面spa
*/3d
搭建測試環境:code
建立一張表,模擬實際業務中的一個表,往裏面填入數據,
時間字段上,相對按照時間均勻地填充,其餘字段以GUID填充htm
Create table BusinessInfoTable ( BuniessCode1 varchar(50), BuniessCode2 varchar(50), BuniessCode3 varchar(50), BuniessCode4 varchar(50), BuniessStatus1 tinyint, BuniessStatus2 tinyint, BuniessDateTime1 Datetime, BuniessDateTime2 Datetime, OtherColumn1 varchar(50), OtherColumn2 varchar(50), OtherColumn3 varchar(50) ) declare @i int=0 while @i<1000000 begin insert into BusinessInfoTable values ( NEWID(),NEWID(),NEWID(),NEWID(),RAND()*100,RAND()*100, DATEADD(MI,@i,GETDATE()),DATEADD(MI,@i,GETDATE()),NEWID(),NEWID(),NEWID() ) set @i=@i+1 end
如今有這麼一個查詢(實際上查詢遠比這個複雜,我簡化一點,不要說我刻意造環境)blog
select OtherColumn2, BuniessStatus1, BuniessStatus2, BuniessDateTime1, BuniessDateTime2 from BusinessInfoTable where BuniessDateTime1 between '2016-6-21' and '2016-6-28' and BuniessDateTime2 between '2016-6-21' and '2016-6-28' and BuniessStatus1 = 55 and BuniessStatus2 = 66
鄭重的說明一點:
暫時不考慮彙集索引,畢竟一個表上只能有一個彙集索引,
別人也不是傻子,不會輕易去建彙集索引,彙集索引早被佔用了
既然被佔用了,個人原則是通常不去動別人現有的東西的,好比別人建了彙集索引,你給人家刪了,根據本身的狀況建彙集索引
這不是找罵麼
有經驗的你必定考慮符合索引了,同時考慮到爲避免Key Lookup致使的書籤查找,咱們把查詢索要的OtherColumn2列include進來
好比這樣
CREATE NONCLUSTERED INDEX IDX_1 ON BusinessInfoTable (BuniessStatus1,BuniessStatus2,BuniessDateTime1,BuniessDateTime2) INCLUDE(OtherColumn2)
或者這樣,只是索引列順序不同
CREATE NONCLUSTERED INDEX IDX_1 ON BusinessInfoTable (BuniessDateTime1,BuniessDateTime2,BuniessStatus1,BuniessStatus2) INCLUDE(OtherColumn2)
固然能夠隨意調整四個列的順序,我就不過多地作演示了,有興趣的本身試
這裏的前導列的順序並不會影響到索引的使用,查詢的時候都是非彙集索引Seek,絕對的
那麼問題來了,徹底同樣的查詢條件,結果同樣,使用不一樣的索引,索引的區別僅僅是列順序不同,其代價同樣嗎,先猜想一下,有區別嗎?
一樣查詢,使用不一樣索引的結果(分別是上面的IDX_1和IDX_2):
下面看圖說話
看看IO狀況
緣由分析
看來是有點差異吧,好彷佛這個差異還真不小(以往寫文章,我測試環境弄很差,對比出來的效果不明顯,感受沒啥說服力,此次對比仍是比較明顯的)
究竟緣由在何?
索引是以平衡樹(B樹)的方式存在的,複合索引的列的順序決定了B樹的信息的存儲的順序
若是是以BuniessStatus1列爲前導列,由於BuniessStatus1分佈的範圍(相對)較小,
這樣在查詢的時候經過BuniessStatus1=55就能夠過濾出來一個比較小的結果集,後面依次用其餘條件過濾就相對較快了
好比BuniessStatus1=55過濾出來符合條件的數據有5條,
加上BuniessStatus2 BuniessDateTime1 BuniessDateTime2 這三個條件再過濾,出來一條數據。
若是BuniessDateTime1 是索引的前導列,用BuniessDateTime1 between '2016-6-21' and '2016-6-28'過濾
可能會有10000條數據,而後依次再用 BuniessDateTime2,BuniessStatus1, BuniessStatus2過濾
最後也只有一條符合條件的數據。
差異就在於:一開始的過濾條件,決定了查詢多少page初步肯定知足條件的數據,再進一步的進行過濾
若是最開始就相對精確地肯定了知足查詢條件的數據範圍,後面能夠經過相對較小的代價來最終確認出知足條件的數據
若是最開始相對模糊地卻肯定了知足查詢條件的數據範圍,那麼這個過程的代價就相對比較大,雖而後面經過每個條件的過,結果是同樣的
固然這種索引的創建跟數據分佈有關,
可是,我沒有下結論說,複合索引必定要按照什麼什麼順序來是最好的
仍是那句話:具體問題具體分析,避免經驗主義,沒有一刀切的手段能夠解決全部的問題。
總結:
本文經過一個簡單的例子,分析了建立符合索引時,列的順序對查詢的影響,說明在建立索引的時候,不只僅要考慮在哪些列上建立索引,同時也要注意到,索引列的順序,是否會對查詢產生影響。避免一說到索引,就是「在查詢條件上建索引」的暴力作法。