全值匹配
查询字段与所有的索引一一对应才可以使所有索引都生效
最左前缀法则
如由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,classid,name); //创建索引
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.在选择组合索引的时候,当前查询中过滤性最好的索引越靠前越好
过滤性越好,筛选剩余的数据越少,给后面查询的压力越小
3.在选择组合索引的时候,尽量选择能够包含当前查询中的where子句中更多字段的索引
4.在选择组合索引的时候,如果某个字段可能出现范围查询时,尽量把这个字段放在索引次序的最后面