1. 1. 一、MySQL客户端和服务器通讯
  2. 2. 二、查询缓存
    1. 2.1. 2.1 查询缓存
    2. 2.2. 2.2 解析和预处理
    3. 2.3. 2.3 查询优化器
    4. 2.4. 2.4 查询执行计划
    5. 2.5. 2.5 查询执行引擎
  3. 3. 三、将查询结果返回客户端

想要学好一门技术,最基本的要求是摸清其原理和作用。学习MySQL也是如此,只有清晰的理解SQL语句执行的整个过程,才能更好的进行SQL的编写和优化。

MySQL执行一个查询的过程,到底做了些什么?
鉴于流程图如下:

大致流程描述:

  • MySQL客户端通过协议将SQL语句发送给MySQL服务器
  • 服务器会先检查查询缓存中是否有执行过这条SQL,如果命中缓存,则将结果返回,否则进入下一个环节(查询缓存默认不开启)
  • 服务器端进行SQL解析,预处理,然后由查询优化器生成对应的执行计划
  • 服务器根据查询优化器给出的执行计划,再调用存储引擎的API执行查询
  • 将结果返回给客户端,如果开启查询缓存,则会备份一份到查询缓存中

一、MySQL客户端和服务器通讯

MySQL 客户端和服务器之间的通讯协议是“半双工”的,这意味着,在任何一个时刻,要么由服务器向客户端发送数据,要么由客户端向服务器发送数据,这两个动作不能同时发生。这种协议让 MySQL 通信简单快速,但也限制了 MySQL。一个明显的限制是,这意味着没办法进行流量限制。一旦一端开始发生消息,另一端要接收完整个消息才能响应他。

客户端用一个单独的数据包将查询传给服务器。一旦客户端发送了请求,他能做的事情就只是等待结果了。在数据库层执行SQL语句时,应用程序会连接到相应的数据库服务器,把SQL语句发送给服务器处理

二、查询缓存

2.1 查询缓存

MySQL查询缓存会保存查询返回的完整结构。当查询命中该缓存时,在返回查询结果之前 MySQL 会检查一次用户权限。如果权限没有问题,MySQL 会跳过解析、优化和执行阶段阶段,直接从缓存中拿到结果并返回给客户端。这种情况下,查询不会被解析,不会生成执行计划,不会被执行。但查询缓存是默认不开启的,且要求 SQL 和参数都是一样,同时查询缓存系统会跟踪查询中涉及的每一个表,如果这些表发生变化,则该表相关的所有缓存数据均会失效

2.2 解析和预处理

如果查询缓存未命中,则到解析器。解析器主要是对SQL语句进行解析,使用 MySQL语法规则进行验证和解析查询,并生成对应的解析树。
得到解析数之后,还需要做预处理,预处理则进一步检查解释树是否合法,以及进行一些优化,比如检查数据表和列是否存在,如果有计算,会将计算的结果算出来等等

2.3 查询优化器

查询优化器是整个流程中重要的一环。查询优化器会将预处理之后的解析树转化成执行计划。一条查询可以有多种执行方法,最后均会返回相同结果。查询优化器的作用就是找到这其中最好的执行计划

生成执行计划的过程会消耗较多的时间,特别是存在许多可选的执行计划时。如果在一条SQL语句执行的过程中将该语句对应的最终执行计划进行缓存,当相似的语句再次被输入服务器时,就可以直接使用已缓存的执行计划,从而跳过SQL语句生成执行计划的整个过程,进而可以提高语句的执行速度。
通常所讲的优化SQL,其实就是想让查询优化器,按照我们的思路,帮我们选择最优的执行方案

2.4 查询执行计划

查询执行计划,就是 MySQL 查询中的执行计划,比如是执行 WHERE 语句还是 FROM 语句

  1. FROM table1 left join table2 on 将table1和table2中的数据产生笛卡尔积,生成Temp1
  2. JOIN table2 所以先是确定表,再确定关联条件
  3. ON table1.column = table2.columu确定表的绑定条件 由Temp1产生中间表Temp2
  4. WHERE 对中间表Temp2产生的结果进行过滤 产生中间表Temp3
  5. GROUP BY 对中间表Temp3进行分组,产生中间表Temp4
  6. HAVING 对分组后的记录进行聚合 产生中间表Temp5
  7. SELECT 对中间表Temp5进行列筛选,产生中间表 Temp6
  8. DISTINCT 对中间表 Temp6进行去重,产生中间表Temp7
  9. ORDER BY 对Temp7中的数据进行排序,产生中间表Temp8
  10. LIMIT 对中间表Temp8进行分页,产生中间表Temp9

2.5 查询执行引擎

执行计划会传给查询执行引擎,执行引擎选择存储引擎来执行计划,到磁盘中的文件中去查询。

三、将查询结果返回客户端

查询执行的最后一个阶段是将结果返回给客户端。即使查询不需要返回结果给客户端,MySQL 仍然会返回这个查询的一些信息,如该查询影响到的行数。如果查询可以被缓存,那么 MySQL 在这个阶段也会将结果放到查询缓存中