一、聯合索引的B+樹
索引失效我們針對的是聯合索引,我們之前有講到過,在沒有遵守最佳左法則或者使用like或者使用百分號的情況下索引會失效。但是到底為什么索引失效了並沒有解釋。索引失效和innodb引擎的B+樹存儲方式有關。我們知道單索引的B+樹是這樣的。
聯合索引的B+樹也相差不多,因為聯合所有有多個字段,下面的圖以兩個字段為例子,比如兩個字段為(a,b),其實和單值索引的不同至少他的鍵值對不是一個,而是多個
我們現在分析這個構建出來的樹
當我們只分析a時,會發現a是有序的,1,1,2,2,3,3
當我們只分析b時,會發現b是無序的,1,2,1,4,1,2
但是如果我們先根據a排序,再來看b,就會發現在a確定的情況b其實也是有序的。
這個就是我們聯合索引命中的原理。即a本身有序,在a確定的情況下,b又是有序的,所以就相當於都是有序的
二、最佳左前綴法則
根據上圖我們就可以理解為什么在我們沒有遵守最佳左前綴法則的時候無法命中索引。看下面的例子
select * from test where a=1 and b=2;
-- 上述語句是直接命中索引的,首先找a,a是有序的,在確定了a之后找b,在a確定后b也是有序的。
select * from test where b=2;
-- 上述語句未命中索引,此時在構建的樹中,b是無序的,無法使用二分查找。mysql找無序的數據就是全表掃描。
三、范圍查找右邊失效原理
其實和上面相同,當你使用了范圍查找,能夠鎖定部分的a值,但是去除掉了這些a之后,還有許多其他的a值綁定的b值依然是無序的。
select * from test where a>1 and b=2;
要找到一個b有序的前提是缺點a的值,范圍查找中大於a的值可能是一個,也可能是一百萬個。
四、like索引失效原理
like一般要配合百分號,一般是查字符類型的。在mysql里字符會按照自己的算法排好,當然也是從小到大,如字母就是用ascii碼表排序。
a%代表找以a開頭的所有,a叫前綴
%a%代表任意包含a的值,a叫中綴
%a代表找以a結尾的所有,a叫后綴
根據我們之前是結論,要命中索引必須要確定a的值,那么只有a%是符合的,因為后兩種都無法確定前面的值,但是這種僅僅只有一個a%其實也是很難命中索引的,因為a開頭的值可能有一個,也可能一百萬個。