【MySQL | 第十篇】重新认识MySQL索引匹配过程

文章目录

10.重新认识MySQL索引匹配过程

​ MySQL 的索引匹配过程是数据库查询优化中的关键部分。

10.1匹配规则

经过分析总结,MySQL 索引匹配的一般规则一共有:五种

  • 等值匹配、最左匹配原则、列前缀匹配、匹配范围值、索引覆盖
  1. 等值匹配:

    如果查询条件是等值匹配,即 = 操作符,MySQL 可以高效地使用索引来查找匹配的行。这种情况下,MySQL 会直接根据索引中的值找到匹配的记录。

  2. 最左匹配原则:

    MySQL 的组合索引使用最左匹配原则,即只有当查询条件匹配索引的最左侧列时,索引才会被使用。例如,对于 (a, b, c) 的组合索引,查询条件只包含 aa, ba, b, c 才会使用索引。

    • mysql会一直向右匹配直到遇到范围查询(>、<)就停止匹配(注意:对于 >=、<=、BETWEEN、like 前缀匹配这四种范围查询,并不会停止匹配),
    • 比如a = 1 and b = 2 and c > 3 and d = 4
      • 如果建立(a,b,c,d)顺序的索引,d是用不到索引的,
      • 如果建立(a,b,d,c)的索引则都可以用到,a,b,d的顺序可以任意调整(建立索引时他们三个的顺序)
  3. 列前缀匹配:

    可以匹配某一列值的开头部分:

    sql 复制代码
    使用索引: explain select * from staffs where name like 'j%'  ;
    
    索引失效: explain select * from staffs where name like '%j%'  ;
  4. 匹配范围值:

    可以查找某一范围的值:explain select * from staffs where name >'Mary' ;

  5. 索引覆盖:

    如果查询的列都包含在索引中,并且查询不需要访问表数据,即可通过索引得到所有需要的信息,这种情况称为索引覆盖。索引覆盖可以提高查询性能,因为不需要访问表中的实际数据行。

    例子:

    explain select name,age,pos from staffs where name='张三' and age=23 and pos ='dev';

10.2举例:联合索引遇到范围查询(>、<、between、like)

​ 参考链接:联合索引遇到范围查询(>、<、between、like)的情况

  • 错误结论:联合索引的最左匹配原则会一直向右匹配直到遇到范围查询(>、<、between、like) 就会停止匹配。
  • 正确结论联合索引的最左匹配原则,在遇到范围查询(如 >、<)的时候,就会停止匹配,也就是范围查询的字段可以用到联合索引,但是在范围查询字段后面的字段无法用到联合索引。但是,对于 >=、<=、BETWEEN、like 前缀匹配这四种范围查询,并不会停止匹配。

10.2.1例子一:>

Q1: select * from t_table where a > 1 and b = 2;

联合索引(a, b)哪一个字段用到了联合索引的 B+Tree?

  1. 由于联合索引(二级索引)是先按照 a 字段的值排序的,所以符合 a > 1 条件的二级索引记录肯定是相邻的,于是在进行索引扫描的时候,可以定位到符合 a > 1 条件的第一条记录
  2. 然后沿着记录所在的链表向后扫描,直到某条记录不符合 a > 1 条件位置。所以 a 字段可以在联合索引的 B+Tree 中进行索引查询。
  3. 但是在符合 a > 1 条件的二级索引记录的范围里,b 字段的值是无序的
  4. 因此,我们不能根据查询条件 b = 2 来进一步减少需要扫描的记录数量(b 字段无法利用联合索引进行索引查询的意思)。
  5. 因此,Q1 这条查询语句只有 a 字段用到了联合索引进行索引查询,而 b 字段并没有使用到联合索引

10.2.2例子二:>=

Q2: select * from t_table where a >= 2 and b = 7,
联合索引(a, b)哪一个字段用到了联合索引的 B+Tree?

  1. Q2 和 Q1 的查询语句很像,唯一的区别就是 a 字段的查询条件「大于等于」。

  2. 虽然在符合 a>= 1 条件的二级索引记录的范围里,b 字段的值是「无序」的,但是对于符合 a = 1 的二级索引记录的范围里,b 字段的值是「有序」的 (因为对于联合索引,是先按照 a 字段的值排序,然后在 a 字段的值相同的情况下,再按照 b 字段的值进行排序)。

  3. 所以,Q2 这条查询语句 a 和 b 字段都用到了联合索引进行索引查询

10.2.3例子三:between

Q3: SELECT * FROM t_table WHERE a BETWEEN 2 AND 8 AND b = 2,
联合索引(a, b)哪一个字段用到了联合索引的 B+Tree?

  1. Q3 查询条件中 a BETWEEN 2 AND 8 的意思是查询 a 字段的值在 2 和 8 之间的记录。

  2. 不同的数据库对 BETWEEN ... AND 处理方式是有差异的。在MySQL 中,BETWEEN 包含了 value1 和 value2 边界值,类似于 >= and =<

  3. 虽然 a 字段使用了 BETWEEN 进行范围查询,但是联合索引的最左匹配原则并没有在遇到 a 字段的范围查询( BETWEEN)后就停止匹配了,b 字段还是可以用到了联合索引的。

10.2.4例子四:like

Q4: SELECT * FROM t_user WHERE name like 'j%' and age = 22
联合索引(name, age)哪一个字段用到了联合索引的 B+Tree?

  1. 由于联合索引(二级索引)是先按照 name 字段的值排序的,所以前缀为 'j' 的 name 字段的二级索引记录都是相邻的, 于是在进行索引扫描的时候,可以定位到符合前缀为 'j' 的 name 字段的第一条记录,然后沿着记录所在的链表向后扫描,直到某条记录的 name 前缀不为 'j' 为止。
  2. 所以 a 字段可以在联合索引的 B+Tree 中进行索引查询,形成的扫描区间是['j','k')。注意, j 是闭区间。如下图:
  1. 虽然在符合前缀为 'j' 的 name 字段的二级索引记录的范围里,age 字段的值是「无序」的,但是对于符合 name = j 的二级索引记录的范围里,age字段的值是「有序」的(因为对于联合索引,是先按照 name 字段的值排序,然后在 name 字段的值相同的情况下,再按照 age 字段的值进行排序)。

  2. 于是,在确定需要扫描的二级索引的范围时,当二级索引记录的 name 字段值为 'j' 时,可以通过 age = 22 条件减少需要扫描的二级索引记录范围(age 字段可以利用联合索引进行索引查询的意思)。

  3. 也就是说,从符合 name = 'j' and age = 22 条件的第一条记录时开始扫描,而不需要从第一个 name 为 j 的记录开始扫描 。如下图的右边:

所以,Q4 这条查询语句 a 和 b 字段都用到了联合索引进行索引查询

相关推荐
LK_078 小时前
【Open3D】Ch.3:顶点法向量估计 | Python
开发语言·笔记·python
Jabes.yang8 小时前
Java求职面试: 互联网医疗场景中的缓存技术与监控运维应用
java·redis·spring security·grafana·prometheus·oauth2·互联网医疗
li星野8 小时前
打工人日报#20251011
笔记·程序人生·fpga开发·学习方法
摇滚侠8 小时前
Spring Boot 3零基础教程,yml配置文件,笔记13
spring boot·redis·笔记
QT 小鲜肉8 小时前
【个人成长笔记】在Ubuntu中的Linux系统安装 anaconda 及其相关终端命令行
linux·笔记·深度学习·学习·ubuntu·学习方法
初级炼丹师(爱说实话版)8 小时前
内存泄漏与内存溢出
java
QT 小鲜肉8 小时前
【个人成长笔记】在Ubuntu中的Linux系统安装实验室WIFI驱动安装(Driver for Linux RTL8188GU)
linux·笔记·学习·ubuntu·学习方法
CryptoRzz8 小时前
越南k线历史数据、IPO新股股票数据接口文档
java·数据库·后端·python·区块链
急急黄豆8 小时前
MADDPG学习笔记
笔记·学习
专注写bug8 小时前
Springboot——使用shyiko监听mysql的bin-log
mysql·binlog