关于Mysql5.7及8.0版本索引失效情况汇总 目录 一个独立索引 多个独立索引 总结 TIPS: 没有特殊说明,测试环境均为MySQL8.0,早期版本可能会有更多情况导致索引失效.8.0失效的情况,早期版本也失效:8.0不失效的情况,早期版本可能失效. 所有测试默认不考
目录
- 一个独立索引
- 多个独立索引
- 总结
TIPS:
- 没有特殊说明,测试环境均为MySQL8.0,早期版本可能会有更多情况导致索引失效。8.0失效的情况,早期版本也失效;8.0不失效的情况,早期版本可能失效。
- 所有测试默认不考虑表为空的情况,特殊情况文中会有说明。
- 本文只介绍Innodb引擎下的索引失效情况。
一个独立索引
1、使用like且在左边有“%”。
2、隐式类型转换,索引字段与条件或关联字段的类型不一致。
3、条件中对索引列进行运算或使用函数
4、不可空索引使用 is not null,仅当查询列只有该索引列时会使用索引
5、使用OR且存在非索引列
6、使用 NOT IN、IN、IS NULL、IS NOT NULL,且返回值中不止包含条件索引列。
拓展:
- MySQL环境变量eq_range_index_dive_limit的值对IN语法有很大影响,该参数表示使用索引情况下IN中参数的最大数量。MySQL 5.7.3以及之前的版本中,eq_range_index_dive_limit的默认值为10,之后的版本默认值为200。
- 我们拿MySQL8.0.19举例,eq_range_index_dive_limit=200表示当IN (...)中的值 >200个时,该查询一定不会走索引。<=200则可能用到索引。
7、使用非主键范围条件查询时,部分情况索引失效。
8、MySQL5.7,使用 IS NOT NULL或 IS NULL 部分情况下索引失效。
9、MySQL5.7,使用 != 或 IN 或 NOT IN 部分情况下索引失效
10、MySQL5.7,表关联时,关联字段字符集不一致会导致索引失效。
11、MySQL5.7,表关联时,关联字段字符集排序规则不一致会导致索引失效。
多个独立索引
1、使用OR且第一个条件是范围查询,且返回值中不止包含条件索引列。
2、 MySQL5.7,使用OR且存在条件是范围查询,且返回值中不止包含条件索引列。
3、组合索引
扩展:
- 以上两条SQL是可以使用到索引的,原理就是上面提到的索引覆盖,
- 虽然根据最左匹配原则是没法使用索引去快速检索数据的;但是因为该查询中所查询的列是col1,col2,而该索引只包含col1,col2,col3三个字段信息,而主键索引中包含所有字段信息,用该索引做全表扫描的效率更高,所以还是会使用到该索引!
总结
上述所有可能用到可能没用到索引的情况,并不是一定的!导致索引失效的阈值也不一定100%准确,毕竟不同数据类型、不同数据量的情况下,MySQL的优化器的选择可能不同。但可以肯定的是,同样一条语句,可能由于筛选率等原因导致索引失效。
所有简单查询(执行计划中 select_type = simple),只要where条件中有索引列(无论什么条件),且返回值中只包含该索引列(和主键),都会用到索引。根据执行计划中的extra可以区分索引的用途:
1、extra = Using index,表示索引覆盖。
2、extra = Using index, Using where,表示存在回表操作。
拓展:
为什么只要返回值只包含索引和主键就会用到索引?
众所周知,InnoDB保存数据是通过B+树结构存储的。且只有主键索引所在的B+树的叶子节点会保存实际数据,其他节点只保存主键值,这种数据与索引在一起的索引我们称之为聚簇索引。
二级索引(非主键索引)的所有节点除了保存索引列的值外还会保存主键的值。
所以当我们通过二级索引查询数据时,第一步先通过二级索引查询到对应的主键值;再通过主键值到主键索引中查询对应的实际数据,这个过程我们称之为回表。
而回表操作是随机IO,所以性能较差,当需要回表的数据量比较大时,优化器可能就会选择不走索引,直接全表扫描,因为走全表是顺序IO,指不定走全表比走索引还快。(这也解释了为什么同样的SQL,表数据不同查询策略也不同)
其中一个特殊情况是当我们的查询只涉及到索引列和主键的时候,我们就不需要再回表查询实际数据了,因为二级索引中保存了主键和索引列的数据,这个时候就肯定会走索引了。
在复制其他地方提供的sql建表脚本时,注意其字符集和排序规则是否跟自己数据库默认的一致,否则可能出现索引失效的问题。
不同版本不同情况下,索引的使用情况不一致。上文提到的可能使用可能不使用的情况是由MySQL的优化器决定的,可能还会有其他情况下优化器也不使用索引,此时我们可以强制指定需要使用的索引:
以上为个人经验,希望能给大家一个参考,也希望大家多多支持我们。