????上一篇我們從索引的存儲(chǔ)結(jié)構(gòu)分析吸重,說(shuō)到了B Tree索引、Hash索引歪今、FULLTEXT全文索引嚎幸。這一期,我們?cè)趶钠渌麑哟螌W(xué)習(xí)洗索引彤委。
一鞭铆、前期回顧:
從索引存儲(chǔ)結(jié)構(gòu)劃分:B Tree索引、Hash索引焦影、FULLTEXT全文索引以及R Tree索引
從應(yīng)用層次劃分:普通索引、唯一索引封断、主鍵索引斯辰、復(fù)合索引
從鍵值劃分:主鍵、輔助
從數(shù)據(jù)存儲(chǔ)以及索引邏輯關(guān)系劃分:聚集索引坡疼、非聚集索引
二彬呻、索引的分類
2.1、普通索引
????????普通索引既我們平時(shí)常用的索引柄瑰,默認(rèn)使用的是BTree闸氮。
ALTER?TABLE?`user`ADD?INDEX?`index_userNm`?(`username`)?USING?BTREE?COMMENT?'用戶名索引';--?或者ALTER?TABLE?`user`ADD?INDEX?`index_userNm`?(`username`);
2.2、唯一索引
????????與普通索引類似教沾,不同的點(diǎn)在于:索引的值必須唯一蒲跨,允許有空值。換句話說(shuō)?某種程度上說(shuō)的就是表中索引鎖標(biāo)記的唯一列授翻。
ALTER?TABLE?`user`?ADD?UNIQUE?INDEX?`index_un_id`(`id`);
主鍵索引
????????與唯一索引的區(qū)別就是索引標(biāo)記的列不允許有空值或悲,換句話說(shuō)就是主鍵列上加的索引孙咪。
ALTER?TABLE?`user`?ADD?PRIMARY?KEY?(`id`);
2.3、復(fù)合索引
????????又名聯(lián)合索引巡语,也是我們比較常用的索引類型之一翎蹈。在數(shù)據(jù)表的2列或>2列共同組成的索引。而上面我們說(shuō)的普通索引男公、唯一索引荤堪、主鍵索引又叫單一索引。顧名思義是指索引列只有一列枢赔,而用戶可以在多個(gè)列上建立索引澄阳,這種索引就叫復(fù)合索引,也叫組合索引糠爬、聯(lián)合索引寇荧,復(fù)合索引可以代替多個(gè)單一索引,相遇多個(gè)單一索引执隧,復(fù)合索引所需的開(kāi)銷更小揩抡。
在這里復(fù)合索引還有個(gè)小小的區(qū)分:窄索引、寬索引
窄索引:指索引列為1-2列的索引
寬索引:指索引列超過(guò)2列的索引
??索引設(shè)計(jì)原則:能用窄索引不用寬索引镀琉,因?yàn)檎饕冉M合索引更有效
? ?值得我們重點(diǎn)關(guān)注的是:
需要加索引的字段峦嗤,要在where條件中。
數(shù)據(jù)量少的字段不需要加索引屋摔。最窄的字段放在鍵的左邊烁设。
如果where條件中是OR關(guān)系,必須所有的or條件都必須是獨(dú)立索引钓试,否則加索引不起作用装黑。見(jiàn):mysql關(guān)于or的索引問(wèn)題
最左匹配原則。
只要列中包含有NULL值都將不會(huì)被包含在索引中弓熏,復(fù)合索引中只要有一列含有NULL值恋谭,那么這一列對(duì)于此復(fù)合索引就是無(wú)效的。所以我們?cè)跀?shù)據(jù)庫(kù)設(shè)計(jì)時(shí)不要讓字段的默認(rèn)值為NULL挽鞠。
eg:
假設(shè)某個(gè)表有一個(gè)聯(lián)合索引(c1,c2,c3,c4)以下選項(xiàng)哪些字段使用了該索引:
A where c1=x and c2=x and c4>x and c3=x
B where c1=x and c2=x and c4=x order by c3
C where c1=x and c4= x group by c3,c2
D where c1=? and c5=? order by c2,c3
E where c1=? and c2=? and c5=? order by c2,c3
接下來(lái)借用上面的例子疚颊,我們求證一下:
首先創(chuàng)建表:
CREATE?TABLE?t(??c1?CHAR(1)?not?null,??c2?CHAR(1)?not?null,??c3?CHAR(1)?not?null,??c4?CHAR(1)?not?null,??c5?CHAR(1)?not?null)ENGINE?myisam?CHARSET?UTF8;
創(chuàng)建索引:
alter?table?t?add?index?c1234(c1,c2,c3,c4);
隨機(jī)搞兩條數(shù)據(jù):
insert?into?t?VALUES('1','1','1','1','1'),('2','2','2','2','2')
使用MySql Explain開(kāi)始分析題目結(jié)果:
A 選項(xiàng):where c1=x and c2=x and c4>x and c3=x
說(shuō)明下:UTF-8 編碼,一個(gè)索引的長(zhǎng)度為3信认,如上圖我們可以看到材义,c1,c2,c3,c4均使用到了該索引。
但是如果我們將查詢條件調(diào)整下或者去掉一個(gè)嫁赏,索引又是怎么使用的呢:
由上面4個(gè)圖可以看出其掂,我們分別調(diào)整了各個(gè)列的位置居兆,使用>和使用>的位置拘央,發(fā)現(xiàn)索引都是正常使用的,所以可以得出:
使用“<” / “>”并不影響索引的選擇
where條件和創(chuàng)建索引的列保持一致時(shí),條件的位置(順序)并不影響索引的選擇腐螟。
但是争舞,如果我們對(duì)A組where條件做些調(diào)整呢坑鱼?
當(dāng)我們刪除分別其中一個(gè)條件c1酿矢、c2、c3后盔夜,發(fā)現(xiàn)使用索引的個(gè)數(shù)也發(fā)生了變化负饲。得出結(jié)論:
當(dāng)使用復(fù)合索引時(shí),沒(méi)有使用第一個(gè)復(fù)合索引喂链,不觸發(fā)索引的使用
使用復(fù)核索引時(shí)返十,索引的選擇與where的條件順序和索引建立時(shí)的順序是否一致存在關(guān)系,當(dāng)順序中斷時(shí)椭微,后續(xù)的索引列將不被選擇洞坑。
如果我們對(duì)A組where條件做些調(diào)整呢?
當(dāng)我們使用or蝇率,或者like時(shí)迟杂,通過(guò)上面4張圖可以清醒的得出:
當(dāng)使用or時(shí),不會(huì)使用索引
當(dāng)條件順序與索引創(chuàng)建順序一致本慕,且使用?“l(fā)ike”?/?“l(fā)ike%”時(shí)排拷,索引可以正常被選中
當(dāng)條件順序與索引創(chuàng)建順序一致,且使用 “%like%”锅尘,索引無(wú)法被選中
當(dāng)條件順序與索引創(chuàng)建順序不一致時(shí)监氢,且第一個(gè)條件不是索引創(chuàng)建時(shí)的首列,則無(wú)法選中索引
B選項(xiàng):where c1=x and c2=x and c4=x order by c3
通過(guò)上圖可以發(fā)現(xiàn)藤违,key_len長(zhǎng)度說(shuō)明c1浪腐,c2字段用到了該索引,Extra顯示并沒(méi)有使用臨時(shí)表進(jìn)行排序顿乒,說(shuō)明排序是使用了索引的牛欢,但并沒(méi)有計(jì)算在key_len值中,也沒(méi)有起到連接c4的作用淆游,說(shuō)明索引到c3這里是斷掉的。
排序其實(shí)是利用聯(lián)合索引直接完成了的隔盛,即:使用了c1234聯(lián)合索引犹菱,就已經(jīng)使得c1下c2,c2下c3吮炕,c3下c4是有序的了腊脱,所以實(shí)際是排序利用了索引,c3字段并沒(méi)有使用該索引龙亲。
C選項(xiàng):where c1=x and c4= x group by c3,c2
通過(guò)上面兩圖陕凹,能看出使用group by 一般先生成臨時(shí)文件悍抑,再進(jìn)行排序,但是字段順序?yàn)閏2杜耙,c3時(shí)搜骡,并沒(méi)有用臨時(shí)表進(jìn)行排序,而是利用索引排序好的佑女;當(dāng)group by字段為c3记靡,c2時(shí),由于與索引字段順序不一致团驱,所以分組和排序并沒(méi)有利用到索引摸吠。
D選項(xiàng):where c1=? and c5=? order by c2,c3
通過(guò)此圖可以看出 order by 和group by 類似,字段順序與索引一致時(shí)嚎花,會(huì)使用索引排序寸痢;字段順序與索引不一致時(shí),不使用索引紊选。
E選項(xiàng):where c1=? and c2=? and c5=? order by c2,c3
其實(shí)選項(xiàng)E的結(jié)果分析在上述ABCD的結(jié)果中都分析過(guò)了啼止,這里只有c1,c2字段使用了該索引丛楚。
綜上所述問(wèn)題答案:
????A:四個(gè)字段均使用了該索引
????B:c1族壳,c2字段使用了該索引
????C:c1字段使用該索引
????D:c1字段使用該索引
????E:c1,c2字段使用了該索引
三趣些、小結(jié):
索引的最左原則(左前綴原則)仿荆,如(c1,c2,c3,c4....cN)的聯(lián)合索引,
where 條件按照索引建立的字段順序來(lái)使用(不代表and條件必須按照順序來(lái)寫)坏平,
如果中間某列沒(méi)有條件拢操,或使用like會(huì)導(dǎo)致后面的列不能使用索引。
索引也能用于分組和排序舶替,分組要先排序令境,在計(jì)算平均值等等。所以在分組和排序中顾瞪,如果字段順序可以按照索引的字段順序舔庶,即可利用索引的有序特性。
不知不覺(jué)寫到這又有 2.5k 多字了陈醒,本期我們就寫到這里惕橙,下期我們繼續(xù)
探討索引。
…………………………………分割線……………………………
不積跬步钉跷,無(wú)以至千里弥鹦;不積小流,無(wú)以成江海爷辙。
關(guān)注我彬坏,每天分享一些小知識(shí)點(diǎn)朦促。分享自己的小心得,包含但不限于初栓始、中务冕、高級(jí)面試題呦!;焯稀洒疚!
我都墨跡這么半天了 ,你不點(diǎn)關(guān)注坯屿,不點(diǎn)贊油湖,不收藏,還不轉(zhuǎn)發(fā)领跛,你想干啥7Φ隆!吠昭!