小知识一:MYSQL索引失效?like原理?曾经的我哭了!

40 阅读3分钟

本文根据一个案例介绍MYSQL索引失效的原因,并且顺便介绍索引的特性

案例

场景

画板

问题

经过explain 后,发现并没有命中索引,大家想想为啥?

结论

mysql中 like 后不能紧跟%,这样索引会失效,因为不知道如何查找索引。

画板

索引的特性

1. 回表

当二级索引去找叶子节点,然后根据叶子节点中主键id去找主键索引,此时找到数据行,称为回表。
回到主键索引树搜索的过程,叫做回表。

2. 如何避免回表?

覆盖索引: 如果我们把被选择的字段加入到where 字段的索引中,无需去主键索引中找数据了。直接通过二级索引就能拿到数据。

目的: 减少搜索树的次数,提升查询性能。

2.1 最左前缀原则

联合索引的最左N个字段,也可是字符串索引的最左M个字符。

B+树就是采用索引的最左前缀原则,来定位记录的.

联合索引: 其实就是多个字段组成的组合索引.

覆盖索引:如果查询条件使用的是普通索引(或是联合索引的最左原则字段),查询结果是联合索引的字段或是主键,

不用回表操作,直接返回结果,减少IO磁盘读写读取数据.

小案例:

请问已经有了一个name_age联合索引,还需要一个name索引吗?
alter table table_name add index idx_name_age(name, age);

('李四', 22), ('王五',33),('张三', 10),('张三', 10),('张三',20),('六六',40)
不需要?为哈? 
因为索引中的索引项是根据索引定义中的字段顺序排序的。
此时
select * from user where name = '张三';  此时就会命中idex_name_age
select * from user where name like '张%'; 也会, 但是'%三'会使命中索引失效 

2.2 建立联合索引的原则

  • 如果通过调整顺序,可以少维护一个索引,那么这个顺序就可以优先考虑. 如果有name_age, age此时我看第二个.
  • 空间问题, 如果name字段是比age大的,新建name_age, age两个索引. 因为age查询时,无法命中name_age。
    • 所以,还是那句话,索引的索引项是根据索引定义中的字段顺序排序的。
  • 可以通过索引选择性来看name和age的顺序
    • select count(distinct name)/count(name), count(distinct age)/count(age) from table\G.

3. 索引下推

联合索引idx_name_age 假如一个select * from table where name like 'hello%' and age >10检索.

  • MySQL5.6版本之前,会对匹配的数据进行回表查询. 也是只会命中name开头hello的数据,然后回表.
  • 5.6版本之后,也是只会命中name开头hello的数据C,并且会先过滤C中的age<10(不满足条件的)数据,然后在进行查询,

减少回表率,提升检索速度。

下一章:删除表数据后,表文件大小没有变化?