全值匹配

查询字段与所有的索引一一对应才可以使所有索引都生效

最左前缀法则

如由id,name,phone组成的联合索引,只查询name和phone则索引不生效,必须严格按照创建索引的顺序

计算、函数、类型转换(手动或自动)导致索引失效

如:EXPLAIN SELECT SQL_NO_CACHE * FROM student WHERE student.name LIKE ‘abc%’;

EXPLAIN SELECT SQL_NO_CACHE * FROM student WHERE LEFT(student.name,3) = ‘abc’;

使用left则会导致索引失效 原因是不知道name的值,而是把所有的值全取出再去前三个字符,判断是否与abc相等,并不会使用到索引

返回条件右边的列索引失效

create index idx_age_name_classid on student(age,classidname); //创建索引

EXPLAIN SELECT SQL_NO_CACHE * FROM student
WHERE student.age=30 AND student.classId>20 AND student.name = ‘abc’ ;

上述sql name未使用索引(与写的条件的顺序无关 )

改正:创建索引的时候把name写到返回条件classid的前面

create index idx_age_name_classid on student(age,name,classid);

不等于(!=或者<>)导致索引失效

原因:在B+树中,若查找具体某个值如(where id = 1) 则可以精确查找,但是不等于则无法查找,所以不等于会导致索引失效,只能一个一个去查找再判断是否相等

is null可以使用索引,is not null 不能使用索引

与上述不等于的情况类似,is null相当于等于某个值(值为null) 而is not null 相当于不等于某个值,不能使用索引判断

like以通配符%开头导致索引失效

如where name like ‘%abc’;

or前后存在非索引的列导致索引失效

EXPLAIN SELECT SQL_NO_CACHE * FROM student WHERE age = 10 OR classid = 100;

若上述SQL只有age或classid作为索引则会导致索引失效,只有or前后的字段有索引才可以生效

数据库和表的字符集统一

不同的字符集进行比较之前需要进行转换,使用到转换函数,导致索引失效

总结:

1.对于单列索引,尽量选择针对当前查询过滤性更好的索引

2.在选择组合索引的时候,当前查询中过滤性最好的索引越靠前越好

  1. 过滤性越好,筛选剩余的数据越少,给后面查询的压力越小

3.在选择组合索引的时候,尽量选择能够包含当前查询中的where子句中更多字段的索引

4.在选择组合索引的时候,如果某个字段可能出现范围查询时,尽量把这个字段放在索引次序的最后面