MySQL-查询执行的基础

269 阅读3分钟

MySQL执行一个查询的过程,如下图所示:

  1. 客户端发送一条查询给服务器
  2. 服务器先检查查询缓存,如果命中了缓存,则立刻返回存储在缓存中的结果。否则进入下一阶段
  3. 服务器端进行SQL解析、预处理,再由优化器生成对应的执行计划
  4. MySQL根据优化器生成的执行计划,调用存储引擎的API来执行查询
  5. 将结果返回给客户端

MySQL客户端/服务端通信协议

MySQL客户端和服务端之间的通信协议是“半双工”的,这意味着,在任何一个时刻,要么是由服务器向客户端发送数据,要么是由客户端想服务器发送数据,这两个动作不能同时发生。所以,无法也无须将一个消息切成小块独立发送

查询缓存

在解析一个查询语句之前,如果查询缓存是打开的,那么MySQL会优先检查这个查询是否命中缓存的数据。

如果当前查询命中查询缓存,那么在返回查询结果之前MysQL会检查一次用户权限。如果权限没有问题,MySQL会跳过所有其他阶段,直接从缓存中拿到结果返回给客户端

查询优化处理

在这个阶段,包含多个子阶段:解析SQL、预处理、优化SQL执行计划。这个过程中任何错误都可能终止查询

语法解析器和预处理

首先MySQL通过关键字将SQL语句进行解析,并生成一颗对应的“解析树”。MySQL解析器将使用MySQL语法规则校验和解析校验。

查询优化器

如果语法树被认为是合法的,那么将由优化器转化成执行计划。

下面是一些MySQL能够处理的优化类型:

  • 重新定义关联表的顺序
  • 将外链接转化成内链接

并不是所有的OUTER JOIN语句都必须以外链接的方式执行。例如WHERE条件、库表结构都可能会让一个外链接等价于一个内链接。MySQL能够识别这点并重写查询,让其可以调整关联顺序

  • 使用等价变换规则

MySQL可以使用一些等价变换来简化并规范表达式。它可以合并和减少一些比较。比如(5=5 AND a>5) 将被改写为a>5。

  • 优化COUNT(),MIN()和MAX() 索引和列是否可为空通常可以帮助MySQL优化这类表达式。例如,要找到某一列的最小值,只需要查询对应B-Tree索引最左端的记录,MySQL可以直接获取索引的第一行记录。如果要查询最大值,也只需要读取B-Tree索引的最后一条记录。

  • 预估并转化为常数表达式

  • 覆盖索引扫描
  • 子查询优化 MySQL在某些情况下将子查询转换成效率更高的形式
  • 提前终止查询 在发现已经满足查询需求的时候,MySQL总是能够立即终止查询。比如limit子句,还比如不成立的条件
SELECT * FROM film where film_id=-1;
  • 等值传播

  • 列表IN()比较