对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%'
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
|---|---|---|---|---|---|---|---|---|---|---|---|
| 1 | SIMPLE | employees | range | idx_name_salary | idx_name_salary | 63 | 10 | 1.23 | Using index condition |
确实走了索引
然后使用不符合最左前缀的查询顺序
explain select * from employees
where SALARY like '1%' and EMAIL like 'A%' and FIRST_NAME like 'a%';
但结果是也走了索引:
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
|---|---|---|---|---|---|---|---|---|---|---|---|
| 1 | SIMPLE | employees | range | idx_name_salary | idx_name_salary | 63 | 10 | 1.23 | Using index condition |
但是如果没有firstName字段,就不会走索引
explain select * from employees
where SALARY > 100 and EMAIL like 'A%'
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
|---|---|---|---|---|---|---|---|---|---|---|---|
| 1 | SIMPLE | employees | ALL | 107 | 3.7 | Using 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%'
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
|---|---|---|---|---|---|---|---|---|---|---|---|
| 1 | SIMPLE | employees | ALL | idx_name_salary | 107 | 3.7 | Using where |
如上的两个都没有走索引,虽然firstName在第一位,但是它不是等值查询,会先查like,自然就不符合最左前缀,所以不走索引,改为如下就会走索引了。
explain select * from employees
where FIRST_NAME ='z' and SALARY > 100 and EMAIL like 'A%'
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
|---|---|---|---|---|---|---|---|---|---|---|---|
| 1 | SIMPLE | employees | range | idx_name_salary | idx_name_salary | 68 | 1 | 11.11 | Using index condition |