看这篇就够了!MySQL 索引知识点超全总结( 四 )


select * from employees where hire_date > '1990-01-14' and first_name like 'Hi%';

  • 在 MySQL 5.5 执行 explain,extra 字段的值显示没有使用索引

看这篇就够了!MySQL 索引知识点超全总结

文章插图
 
执行查询花费时间为 0.12s
看这篇就够了!MySQL 索引知识点超全总结

文章插图
 
  • 在 MySQL 5.7 执行 explain,extra 字段的值显示使用了索引下推

看这篇就够了!MySQL 索引知识点超全总结

文章插图
 
执行查询花费时间为 0.02s
看这篇就够了!MySQL 索引知识点超全总结

文章插图
 
  • 索引下推
explain 结果中的 extra 字段值包含 using index condition,则说明使用了索引下推 。索引下推功能是从 5.6 版本开始支持的 。在 5.6 版本之前,i_first_name 索引是没有使用上的,需要每次去主键索引表取完整的记录值进行比较 。从 5.6 版本开始,由于索引 i_first_name 的存在,可以直接取索引的 first_name 值进行过滤,这样不符合"first_name like 'Hi%'"条件的记录就不再需要回表操作 。
MRR 优化MySQL 5.6 版本开始支持 Multi-Range Read(MRR)优化,MRR 优化的目的是为减少磁盘的随机访问,并且将随机访问转化为较为顺序的数据访问,对于 IO-bound 类型的 SQL 查询语句可带来性能极大提升 。我们先看下对比测试,以下测试语句在同一个 MySQL 实例下执行,执行前均进行 mysql 服务重启,以保证缓存此没被预热 。
  • 关闭 MRR
SET @@optimizer_switch='mrr=off';select * from employees where hire_date > '1990-01-14' and first_name like 'Hi%';执行耗时为 0.90s
看这篇就够了!MySQL 索引知识点超全总结

文章插图
 
  • 开启 MRR
SET @@optimizer_switch='mrr=on,mrr_cost_based=off'; select * from employees where hire_date > '1990-01-14' and first_name like 'Hi%';
看这篇就够了!MySQL 索引知识点超全总结

文章插图
 
  • 分析
从测试结果可以发现在 mrr 从关闭到开启,耗时从 0.90s 减少到 0.03s,查询速率达到 30 倍的提升 。
常见的索引失效场景在 MySQL 表中建立了索引,SQL 查询语句就会一定使用到索引么?不一定,存在着索引失效的场景 。我们给 employees 表增一个组合索引,后续例子均基于此表进行分析、测试 。
alter table employees add index i_b_f_l(birth_date, first_name, last_name)alter table employees add index i_h(hire_date);
看这篇就够了!MySQL 索引知识点超全总结

文章插图
 
失效场景
  • 范围查询(>,<,<>)
explain select * from employees where hire_date > '1989-06-02';
看这篇就够了!MySQL 索引知识点超全总结

文章插图
 
  • 查询条件类型不一致
alter table employees add index i_first_name (first_name);explain select * from employees where first_name = 1;
看这篇就够了!MySQL 索引知识点超全总结

文章插图
 
  • 查询条件使用了函数
explain select * from employees where CHAR_LENGTH(hire_date) = 10;
看这篇就够了!MySQL 索引知识点超全总结

文章插图
 
  • 模糊查询
explain select * from employees where hire_datelike'%1995';
看这篇就够了!MySQL 索引知识点超全总结

文章插图
 
  • 不使用组合索引的首个字段当条件
explain select * from employees where last_name = 'Kalloufi' and first_name = 'Saniya';
看这篇就够了!MySQL 索引知识点超全总结

文章插图
 
为什么会失效?