0%

mysql select 的执行流程

本文介绍MySQL的逻辑架构,引出一条select语句的执行流程

MySQL逻辑架构

MySQL逻辑架构图

MySQL的逻辑架构可以分为Server层存储引擎层两部分

Server层包括连接器、查询缓存、分析器、优化器、执行器等;存储引擎层负责数据的存储和提取。其架构模式是插件式的,支持InnoDB、MyISAM、 Memory等多个存储引擎

注:MySQL8.0将查询缓存删除

Server 层

连接器

负责建立、维持、管理客户端的连接,权限认证

查询缓存

将之前执行过的查询语句及其结果以key-value对的形式缓存到内存中,如果能够直接在这个缓存中找到key,则直接返回查询结果

只要有一个表的更新,这个表的查询缓存就会被清空,导致查询缓存的失效非常频繁,如果查询缓存的命中率非常低,则反而影响了效率

MySQL8.0将查询缓存删除

分析器

对查询语句做语法分析

优化器

选择索引,join多表关联时,决定各表的连接顺序

执行器

  1. 判断用户对表是否有执行查询的权限
  2. 调用搜索引擎的接口取值

存储引擎层

只讨论InnoDB

Server层的执行器调用存储引擎的接口,如使用索引name查询name=Tom 的记录,这个流程是什么样的呢

首先介绍索引的类型,以及几种索引机制

索引类型

image-20220917124719018

索引类型分为主键索引(聚簇索引)和非主键索引(二级索引)

  • 如果语句是select * fromTwhere ID=500,主键查询方式,只需要搜索ID这棵B+树;

  • 如果语句是select * fromTwhere k=5,普通索引查询方式,需要先搜索k索引树,得到ID的值为500,再到ID索引树搜索一次。这个过程称为回表

可以看到回表会增加一次索引查询,在范围查询中,如select id, name from user where age > 10,则需要回表很多次,如何避免回表,提高效率呢

覆盖索引

如果select的字段在一个二级索引中已包含,则不需要回表,这个二级索引对于覆盖了查询需求的语句是一个覆盖索引

如 select id, name, age from user where name like 'Jane%' and age < 18; 建立一个联合索引A (name, age),在A中,已经包含了要查询的id, name, age信息,无需回表

最左前缀匹配

最左前缀匹配是针对联合索引而言

如下,为(name, age)的联合索引

image-20220917130645020

索引项是按照索引定义里面出现的字段顺序排序的,匹配时按照从左至於的顺序匹配

  • 只要是联合索引的那几个条件与where子句中的条件匹配,都能应用对应的联合索引
  • 在有联合索引(a+b)和单列索引a同时存在时,通过a条件的查询会优先使用联合索引
  • 在联合索引(a+b)中无法只通过条件b查询,因为b无法匹配最左前缀,这时只能再建一个(b)索引

索引下推

对于mysql> select * from user where name like '张%' and age=10 and ismale=1;

在MySQL 5.6之前,只能从第一个满足【张*】的记录开始一个个回表。到主键索引上找出数据行,再对比字段值

而MySQL 5.6 引入的索引下推优化(index condition pushdown), 可以在索引遍历过程中,对索引中包含的字段先做判断,直接过滤掉不满足条件的记录,减少回表次数

如联合索引 (name, age),会找到 name 和 age 符合条件的 id,再回表

根据上述的索引查找机制,对于一个查询,走哪个索引,是否要回表,就有了一定的认知,进而可以对一些场景进行优化

索引的优化

  • 覆盖索引:对于频繁查询 select name, age from user where age between (10, 20),建立联合索引(age, name)避免回表
  • 索引下推:对于查询 select * from user where name like '张%' and age > 10; 建立联合索引(name, age),相对于单个name索引,可以减少回表次数

题外话:在用户表中,有身份证号的字段,要不要用身份证号做主键

分析:

  1. 身份证是无序的,在维护主键索引树的时候,需要挪动其他记录,引发叶分裂
  2. 身份证号长度较大,主键长度越大,二级索引的叶子节点长度就越大,二级索引占用的空间就越大

答案:不要

用自增id做索引,在主键索引中,每次插入一条新记录,都是追加操作,不涉及到挪动其他记录,也不会触发叶子节点的分裂,相比于身份证长度要短:+1:

总结

本文介绍了MySQL的逻辑架构,包括Server层和存储引擎层,Server层包括连接器、查询缓存、分析器、优化器、执行器;存储引擎层介绍了索引类型,如何通过索引找到记录,索引的一些机制,如覆盖索引、最左前缀匹配、索引下推,最后列举了两个索引的优化策略。一条select语句,就是通过Server层和索引层,最终找到对应的记录

参考文献

mysql 45 讲 第1,4,5讲