Mysql:索引失效的常见场景
索引失效的常见场景
不符合最佳左前缀原则
比如说现在创建一个联合索引:index_union(name,age),然后你的select语句是这样的
select * from user where age = 18
此情况下并不会触发index_union,因为where没使用上name
查询语句中存在函数,计算,数据类型转换
比如说现在创建两个普通索引:index_name(name)和index_age(age),然后你的select语句是这样的
select * from user where left(name,1) = '李'
select * from user where age + 1 = 80
此情况索引会失效
where使用了联合索引全部字段,但实际只用了一部分
比如说现在创建一个联合索引:index_union(name,age,sex),然后你的select语句是这样的
select * from user where name = 'zhangsan' and age > 50 and sex = 1
此select会用到index_union,但只用到name,age和sex不会用到,因为age是范围查询,优化器就不考虑使用age了
建议:尽量把一些频繁范围查询的字段,放在联合索引的靠后位置,比如说时间字段
!= 导致索引失效
比如说现在创建个普通索引:index_age(age),然后你的select语句是这样的:
select * from user where age != 8
此情况不会触发index_age
is null 触发索引,is not null不触发索引
比如说现在创建个普通索引:index_age(age),然后你的select语句是这样的:
select * from user where age is null //能触发索引
select * from user where age is not null //不能触发索引
建议:如果实际开发中真遇到查询 is not null 又要求查询得快,可以考虑将此字段设计成非空。比如说int类型,用0表示空,varchar用‘’表示空。这样就字段中全是有值的,不需要考虑is not null了
like以通配符%开头的
比如说现在创建个普通索引:index_name(name),然后你的select语句是这样的:
select * from user where name like '李%' //能触发索引
select * from user where name like '%李%' //触发不了索引
OR关联的where条件中存在未索引的字段
比如说现在创建个普通索引:index_name(name),然后你的select语句是这样的:
select * from user where name = 'zhangsan' OR age > 18
此情况不会触发index_name,因为优化器觉得name走索引后,age还要走全表,还不如都直接走全表。