MySQL不符合最左前缀也会走索引的一个思考

116 阅读2分钟

对a,b,c三个字段建立索引,按照最左前缀原则,只有查询顺序为(a),(a,b),(a,b,c)时才会走索引,其他查询顺序都不会走索引,这是网上的说法,但是实践之后不是这样。

首先我创建组合索引:

alter table employees add index idx_name_salary (first_name,salary,email);

首先执行会走索引的组合:

explain select * from employees 
where FIRST_NAME like 'a%' and SALARY like '1%' and EMAIL like 'A%'
idselect_typetablepartitionstypepossible_keyskeykey_lenrefrowsfilteredExtra
1SIMPLEemployeesrangeidx_name_salaryidx_name_salary63101.23Using index condition

确实走了索引

然后使用不符合最左前缀的查询顺序

explain select * from employees 
where SALARY like '1%' and EMAIL like 'A%' and FIRST_NAME like 'a%';

但结果是也走了索引:

idselect_typetablepartitionstypepossible_keyskeykey_lenrefrowsfilteredExtra
1SIMPLEemployeesrangeidx_name_salaryidx_name_salary63101.23Using index condition

但是如果没有firstName字段,就不会走索引

explain select * from employees 
where SALARY > 100 and EMAIL like 'A%'
idselect_typetablepartitionstypepossible_keyskeykey_lenrefrowsfilteredExtra
1SIMPLEemployeesALL1073.7Using where

所以只要有第一个字段存在,那么组合索引的位置不限,都会走索引,mysql会自动优化成符合最左前缀匹配.

**重点:**以上是等值查询的时候满足,mysql的查询优化器会先查等值查询,再查范围查询

explain select * from employees 
where SALARY > 100 and EMAIL like 'A%' and FIRST_NAME <'z'

explain select * from employees 
where FIRST_NAME <'z' and SALARY > 100 and EMAIL like 'A%' 
idselect_typetablepartitionstypepossible_keyskeykey_lenrefrowsfilteredExtra
1SIMPLEemployeesALLidx_name_salary1073.7Using where

如上的两个都没有走索引,虽然firstName在第一位,但是它不是等值查询,会先查like,自然就不符合最左前缀,所以不走索引,改为如下就会走索引了。

explain select * from employees 
where FIRST_NAME ='z' and SALARY > 100 and EMAIL like 'A%' 
idselect_typetablepartitionstypepossible_keyskeykey_lenrefrowsfilteredExtra
1SIMPLEemployeesrangeidx_name_salaryidx_name_salary68111.11Using index condition