之所以会有最左前缀匹配原则和联合索引的索引构建方式及存储结构是有关系的。
首先我们创建的idx_t1_bcd(b,c,d)索引,相当于创建了(b)、(b、c)(b、c、d)三个索引,看完下面你就知道为什么相当于创建了三个索引。
我们看,联合索引是首先使用多列索引的第一列构建的索引树,用上面idx_t1_bcd(b,c,d)的例子就是优先使用b列构建,当b列值相等时再以c列排序,若c列的值也相等则以d列排序。我们可以取出索引树的叶子节点看一下。
索引的第一列也就是b列可以说是从左到右单调递增的,但我们看c列和d列并没有这个特性,它们只能在b列值相等的情况下这个小范围内递增,如第一叶子节点的第1、2个元素和第二个叶子节点的后三个元素。
由于联合索引是上述那样的索引构建方式及存储结构,所以联合索引只能从多列索引的第一列开始查找。所以如果你的查找条件不包含b列如(c,d)、(c)、(d)是无法应用缓存的,以及跨列也是无法完全用到索引如(b,d),只会用到b列索引。
这就像我们的电话本一样,有名和姓以及电话,名和姓就是联合索引。在姓可以以姓的首字母排序,姓的首字母相同的情况下,再以名的首字母排序。
如:
M
毛 不易 178********
马 化腾 183********
马 云 188********
Z
张 杰 189********
张 靓颖 138********
张 艺兴 176********
我们知道名和姓是很快就能够从姓的首字母索引定位到姓,然后定位到名,进而找到电话号码,因为所有的姓从上到下按照既定的规则(首字母排序)是有序的,而名是在姓的首字母一定的条件下也是按照名的首字母排序的,但是整体来看,所有的名放在一起是无序的,所以如果只知道名查找起来就比较慢,因为无法用已排好的结构快速查找。
到这里大家是否明白了为啥会有最左前缀匹配原则了吧。
实践如下列举一些SQL的索引使用情况
1 select * from T1 where b = 12 and c = 14 and d = 3;-- 全值索引匹配 三列都用到 2 3 select * from T1 where b = 12 and c = 14 and e = 'xml';-- 应用到两列索引 4 5 select * from T1 where b = 12 and e = 'xml';-- 应用到一列索引 6 7 select * from T1 where b = 12 and c >= 14 and e = 'xml';-- 应用到一列索引及索引条件下推优化 8 9 select * from T1 where b = 12 and d = 3;-- 应用到一列索引 因为不能跨列使用索引 没有c列 连不上 10 11 select * from T1 where c = 14 and d = 3;-- 无法应用索引,违背最左匹配原则