最近刚好在一边做大项目作业一边回忆MySQL的知识,回顾就回到了索引失效的问题,索性从网上扒拉记录一下给自己加强一下印象。
1.最左匹配原则
在学习Mysql中,经常会遇到这种问题,明明这个字段建了联合索引,但是SQL查询该字段时却不会使用这个索引。难道这索引是假的?
比如索引 example_index:(a,b,c) 是 a,b,c 三个字段的联合索引 (此时很明显索引顺序为a->b->c) ,下列 sql 执行时都无法命中索引 example_index;
select * from table where c = '1';
select * from table where b ='1' and c ='2';
select * from table where a = '3' and c = '2';
如果尝试查询的话可以看出前两个语句明显没有命中索引,但第三个语句命中了却忽略了c索引,如果此时将依索引次序查询的话,就会走索引:
select * from table where a = '1';
select * from table where a ='1' and b ='2';
select * from table where a = '3' and b = '2' and c = '3';
小结: 索引 abc_index:(a,b,c),只会在 where 条件中带有 (a)、(a,b)、(a,b,c) 的三种类型的查询中使用。
以下为网上摘抄的图与原理:
MySQL 建立多列索引(联合索引)有最左匹配的原则,即最左优先:
如果有一个 2 列的索引 (a, b),则已经对 (a)、(a, b) 上建立了索引;
如果有一个 3 列索引 (a, b, c),则已经对 (a)、(a, b)、(a, b, c) 上建立了索引;
如图所示:形如(a,b,c)联合索引的 b+ 树,其中的非叶子节点存储的是第一个关键字的索引 a,而叶子节点存储的是三个关键字的数据。单看a也就是最左边的索引是有序的,而b和c是无序的。而满足a有序的情况下对b,c进行对比时,b是有序的,c是无序的,以此类推...
综上所述: 只有在满足了最左匹配且条件有序无缺时,才能让索引有效匹配,否则索引失效。
like 使用了 %X 模糊匹配和索引字段不是联合索引字段的最左字段的索引失效情况与最左匹配原则有关。
(注意: 右模糊查询不影响最左匹配原则,所以还是可以走索引查询的,而左模糊和左右模糊不行)
2.字段类型不匹配导致的索引失效
进行 SQL 数据查询的时候,where 条件字段类型与实际表中字段类型不匹配的时候,Mysql 会进行隐式的数据类型转换,而类型转换会使用到内置函数,导致在进行数据查询的时候并没有使用索引。这里的情况显然是字符串没有加 单引号' ' 导致被当作数值进行转换。
3.不要在索引上进行运算操作或范围查询
在 where 中条件使用了条件表达式的时候,数据表中的索引就失效了,实际是因为 Mysql 需要将索引字段取出来之后再进行表达式的条件判断,因而进行了全表扫描,导致索引失效。
索引字段实际上是依赖于整个 B+索引树的遍历,而索引树的遍历又依赖于索引树底层叶子节点的有序性。索引保存的是索引列的原始值,如果经过函数计算,Mysql 的解释器无法判断计算后的索引在原来的索引树上是否可以被索引到,因此它就直接放弃使用索引查询了。