mysql 存在索引但不能使用索引的典型场景

Posted 心碎whn

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了mysql 存在索引但不能使用索引的典型场景相关的知识,希望对你有一定的参考价值。

mysql 演示数据库:http://downloads.mysql.com/docs/sakila-db.zip

以%开头的LIKE查询不能够利用B-tree索引


 

explain select * from actor where last_name like \'%NI%\'\\G;

 

 

explain select * from actor where last_name like \'NI%\'\\G;

 

解决办法 

先扫描索引 last_name获取满足条件的%NI%的主键actor_id列表,之后根据主键回表去检索记录,这样访问避开了全表扫描actor表产生的大量IO请求。

explain select * from (select actor_id from actor where last_name like \'%NI%\') a,actor b where a.actor_id = b.actor_id\\G;

 

 

 

数据类型出现隐式转换


 

 

 explain select * from actor where last_name=1\\G;

 

 

 explain select * from actor where last_name=\'1\'\\G; 

 

 

 

复合索引的情况下,查询条件不满足索引最左的原则


 

 

 explain select * from payment where amount=3.98 and last_update=\'2016-02-15 22:12:32\'\\G;

 

 

 

Mysql估计使用索引比全表扫描慢


 

 

update film_text set title =concat(\'S\',title);

explain select * from film_text where title like \'S%\'\\G;

 

 

可以看出全表扫描需要访问的记录rows为1000,代价cost计算为233.53;

通过idx_title_desc_part索引扫描访问记录rows为998,代价cost为1198.6  要高于全表扫描的时间,mysql会选择全表扫描

 

 

 

用or分割开的条件,or前条件有索引,or后的列没有索引


 

 

用or分割开的条件,or前条件有索引,or后的列没有索引,那么涉及的索引不会被用到

 因为or后面的条件没有索引,那么后面的查询肯定要进行全表扫描,在存在全表扫描的情况下,就没有必要多一次索引扫描增加IO访问。

explain select * from payment where customer_id =203 or amount=3.96\\G;

 

 

负向查询(not  , not in, not like, <>, != ,!>,!<  ) 不会使用索引


 

 

 

 

 

独立的列 索引 不能是表达式的一部分


 

 

select * from  xxxx where id+1;

 

以上是关于mysql 存在索引但不能使用索引的典型场景的主要内容,如果未能解决你的问题,请参考以下文章

mysql不等于走索引吗

358mysql索引之三:索引使用注意规则(索引失效--存在索引但不使用索引)

索引失效(存在索引但不使用索引)

MySQL 高级--优化 —— 创建索引原则使用场景和索引失效的情况

mysql里是否使用了函数,索引就不能用了

mysql 索引作用范围