這里重點(diǎn)討論的是復(fù)合索引。(這里的索引都是指BTREE索引)
準(zhǔn)備工作
首先毕荐,我們需要建立一張表翘地,表非常簡單,沒有任何意義
create table t(
c1 char(20),
c2 char(20),
c3 char(20),
c4 char(20),
key idx_t_c1234(c1, c2, c3, c4)
);
其次滚粟,你需要對(duì)explain關(guān)鍵字有一定的了解(可以查看我另一篇文章explain詳解)
下面進(jìn)入重點(diǎn)
左前綴法則
如果索引存在多列寻仗,查詢要從索引的最左前列開始,并且不能跳過索引中的列
索引中的四個(gè)字段都使用:
key表示用到了索引idx_t_c1234,ref列是四個(gè)const表示4個(gè)條件都是常量凡壤,key_len表示使用索引大概的字節(jié)數(shù)署尤,extra中Using where 表示使用了where條件,Using index表示覆蓋索引亚侠,說明select查詢的字段都在索引中可以獲取曹体,不需要去磁盤中找。
中間差個(gè)條件呢,如:
select * from t where c1='a' and c2='b' and c4='d';
此時(shí)key_len的長度是122硝烂,而上面是244箕别;ref中是兩個(gè)const,可以得到此時(shí)只是使用了索引中的c1和c2兩個(gè)字段滞谢。c4失效了串稀。因?yàn)椴盍薱3,中間斷了狮杨,導(dǎo)致索引失效
如果是這樣的呢
select * from t where c1='a' and c2 > 'b' and c3 = 'c';
可以看到key_len是61母截,ref只有一個(gè)const,表示只用到了c1橄教;范圍之后索引全失效清寇,這個(gè)也類似于中間斷了。(如果是5.7以前的版本的話颤陶,這里type會(huì)range颗管,而key_len會(huì)是122,用到了c1和c2兩個(gè)字段)
下面的SQL滓走,有興趣的可以試下
explain select * from t where c2='b' and c3='c' and c4='d';
跟上面類似垦江,從源頭就斷了,索引肯定會(huì)失效;type變?yōu)閕ndex(為啥不是all比吭?可以思考下)
如果修改表結(jié)構(gòu):
alter table add column c5 char(20);
再執(zhí)行上面的sql看看(好好理解兩者的不同)
左前綴法則非常有用绽族,在order by和group by還會(huì)用到
覆蓋索引
覆蓋索引這個(gè)概念其實(shí)非常簡單,但確非常有用衩藤;覆蓋索引是指select查詢的字段都來自index(索引)吧慢,不需要去磁盤中查找,從而提高效率赏表。
在explain關(guān)鍵字中的extra列中如果出現(xiàn)了Using index检诗,表示用到了覆蓋索引。
盡量少用select *,用select *一般都會(huì)導(dǎo)致無法用覆蓋索引(除非所有字段都建索引瓢剿,這很明顯不是明智的做法)
索引列少操作
一般來說逢慌,索引列上做任何操作(計(jì)算、函數(shù)间狂、類型轉(zhuǎn)換(自動(dòng)或手動(dòng)))攻泼,都可能會(huì)導(dǎo)致索引類失效。
少用不等
在索引列上使用!= 或 <> 都可能導(dǎo)致索引失效
慎用null
使用is null 或者is not null也可能會(huì)導(dǎo)致索引失效
自mysql5.6之后鉴象,增加了Using index condition忙菠,使用is null 或者is not null會(huì)使用Using index condition進(jìn)行
優(yōu)化,但是還是慎用纺弊,雖然優(yōu)化了牛欢,依然會(huì)影響效率。
like操作
like操作很可能會(huì)導(dǎo)致索引失效
用like盡量不要在開頭加匹配符
如果這樣寫呢
explain select * from t where c1 like 'a%' and c2 > 'b' and c3 = 'c';
有興趣的可以自己去嘗試下俭尖。
如果非要首位寫匹配符呢氢惋,建議用覆蓋索引。
字符串一定要加單引號(hào)
字符串不加單引號(hào)會(huì)導(dǎo)致索引失效(自動(dòng)類型轉(zhuǎn)換)稽犁,這個(gè)錯(cuò)誤非常難發(fā)現(xiàn),一定要養(yǎng)成好的習(xí)慣
少用or
用or來連接會(huì)導(dǎo)致索引失效
最后說一個(gè)新手常犯的錯(cuò)誤骚亿,在where條件的列上都加上索引已亥。
對(duì)于btree索引而言,獨(dú)立的索引只能用一個(gè)来屠,也就是說虑椎,where條件的列上都加上索引,只能用上一個(gè)索引俱笛,正確的做法是用復(fù)合索引捆姜。