mysql索引最左匹配原則的理解

這是你的表結(jié)構(gòu),有三個字段,分別是id,name,cid

CREATE TABLE `student` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(255) DEFAULT NULL,
  `cid` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `name_cid_INX` (`name`,`cid`),
) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8

索引方面:id是主鍵,(name,cid)是一個多列索引。

下面是你有疑問的兩個查詢:

EXPLAIN SELECT * FROM student WHERE cid=1;

注意下面的index索引

image
EXPLAIN SELECT * FROM student WHERE  cid=1 AND name='小紅';

注意下面的ref索引

image

這里的疑問是:sql查詢用到索引的條件是必須要遵守最左前綴原則,為什么上面兩個查詢還能用到索引?

上述你的兩個查詢的explain結(jié)果中顯示用到索引的情況類型是不一樣的。,可觀察explain結(jié)果中的type字段。你的查詢中分別是:
1. type: index
2. type: ref

解釋:
index:這種類型表示是mysql會對整個該索引進行掃描。要想用到這種類型的索引,對這個索引并無特別要求,只要是索引,或者某個復合索引的一部分,mysql都可能會采用index類型的方式掃描。但是呢,缺點是效率不高,mysql會從索引中的第一個數(shù)據(jù)一個個的查找到最后一個數(shù)據(jù),直到找到符合判斷條件的某個索引。
(掃描索引在一定程度上也比掃描全表要快)

所以:對于你的第一條語句:

EXPLAIN SELECT * FROM student WHERE   cid=1;

判斷條件是cid=1,而cid是(name,cid)復合索引的一部分,沒有問題,可以進行index類型的索引掃描方式。explain顯示結(jié)果使用到了索引,是index類型的方式。


ref:這種類型表示mysql會根據(jù)特定的算法快速查找到某個符合條件的索引,而不是會對索引中每一個數(shù)據(jù)都進行一一的掃描判斷,也就是所謂你平常理解的使用索引查詢會更快的取出數(shù)據(jù)。而要想實現(xiàn)這種查找,索引卻是有要求的,要實現(xiàn)這種能快速查找的算法,索引就要滿足特定的數(shù)據(jù)結(jié)構(gòu)。
簡單說,也就是索引字段的數(shù)據(jù)必須是有序的,才能實現(xiàn)這種類型的查找,才能利用到索引。

有些了解的人可能會問,索引不都是一個有序排列的數(shù)據(jù)結(jié)構(gòu)么。不過答案說的還不夠完善,那只是針對單個索引,而復合索引的情況有些同學可能就不太了解了。

下面就說下復合索引:
以該表的(name,cid)復合索引為例,它內(nèi)部結(jié)構(gòu)簡單說就是下面這樣排列的:

image

mysql創(chuàng)建復合索引的規(guī)則是首先會對復合索引的最左邊的,也就是第一個name字段的數(shù)據(jù)進行排序,在第一個字段的排序基礎上,然后再對后面第二個的cid字段進行排序。其實就相當于實現(xiàn)了類似 order by name asc, cid asc這樣一種排序規(guī)則。

所以:第一個name字段是絕對有序的,而第二字段就是無序的了。所以通常情況下,直接使用第二個cid字段進行條件判斷是用不到索引的,當然,可能會出現(xiàn)上面的使用index類型的索引。這就是所謂的mysql為什么要強調(diào)最左前綴原則的原因。

那么什么時候才能用到呢?
當然是cid字段的索引數(shù)據(jù)也是有序的情況下才能使用咯,什么時候才是有序的呢?觀察可知,當然是在name字段是等值匹配的情況下,cid才是有序的。發(fā)現(xiàn)沒有,觀察兩個name名字為 c 的cid字段是不是有序的呢。從上往下分別是4 5。
這也就是mysql索引規(guī)則中要求復合索引要想使用第二個索引,必須先使用第一個索引的原因。(而且第一個索引必須是等值匹配)。


所以對于你的這條sql查詢:

EXPLAIN SELECT * FROM student WHERE   cid=1 AND name='小紅';

沒有錯,而且復合索引中的兩個索引字段都能很好的利用到了!因為語句中最左面的name字段進行了等值匹配,所以cid是有序的,也可以利用到索引了。

你可能會問:我建的索引是(name,cid)。而我查詢的語句是cid=1 AND name='小紅'; 我是先查詢cid,再查詢name的,不是先從最左面查的呀?

好吧,我再解釋一下這個問題:首先可以肯定的是把條件判斷反過來變成這樣 name='小紅' and cid=1; 最后所查詢的結(jié)果是一樣的。
那么問題產(chǎn)生了?既然結(jié)果是一樣的,到底以何種順序的查詢方式最好呢?

所以,而此時那就是我們的mysql查詢優(yōu)化器該登場了,mysql查詢優(yōu)化器會判斷糾正這條sql語句該以什么樣的順序執(zhí)行效率最高,最后才生成真正的執(zhí)行計劃。所以,當然是我們能盡量的利用到索引時的查詢順序效率最高咯,所以mysql查詢優(yōu)化器會最終以這種順序進行查詢執(zhí)行。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容