过程概览
一.查询缓存
MySQL会用一张引用表,将查询缓存以Key-Value的方式进行缓存,Key是查询语句,Value则是查询语句的结果,并且通过一个哈希值来引用,此哈希值受查询语句整体、当前执行查询的数据库、甚至是客户端协议版本等影响。
在查询缓存阶段,首先会对执行语句的用户进行权限校验 ,有查询该表的权限的用户,才能继续进行。若上一次该查询语句缓存了结果,则可以直接返回结果给Client,直接省去解析、预处理、优化、执行的过程,能够提高数据库查询的性能。
但也正因为未进行解析、预处理,空格、注释(两条语句间任何 字符的不同)也会影响命中率,查询语句中包含了不确定的数据,也不会被缓存,如CURRENT_DATE()、自定义函数、临时表等,若表发生变化,查询缓存可能会失效,所以一般应用于多次使用、读取频繁且数据变化不频繁、数据量大的查询。
查询缓存默认是关闭的,若需要启用查询缓存,通过在服务器配置文件my.cnf 中添加query_cache_type=
1或者query_cache_type=2,若等于2,则只对显示定义SQL_CACHE有效。
确定要执行的查询缓存,可以用SQL_CACHE显示指定:
csharp
select SQL_CACHE column_name from table_name;
由于使用场景较少、可能导致并发性能问题,MySQL在8.0后版本移除了查询缓存。
二.解析器、预处理器
解析器是对查询语句通过词法分析(关键字)、语法解析(语法规则)来生成一个数据结构------解析树(select_lex),词法分析是将SQL语句拆成一个一个单词进行检查,而语法分析则顾名思义,检查语句是否符合SQL的语法规则,在此阶段,并不会对语句中的字段名、表名进行检查。
SQL语句若符合上述条件,则预处理器会进一步检查解析树是否合法,例如表、字段是否存在、命名、别名是否存在歧义,所以当语法错误和字段不匹配同时出现,会先报语法错误。
三.优化器
优化器会根据它认为的最优的执行计划执行,有多个索引,决定使用哪个索引,有多表关联,优先连接哪个表等。优化器会将传入的解析树生成一个/多个执行计划,执行计划的个数跟查询语句中的条件也有关系。生成执行计划会消耗较多时间,特别是当有多个执行计划的时候。
csharp
select name from school where gender = 'Male' and class = 9;
Plan A:先在school表中找出gender字段值为'Male'的行,再判断class字段值是否为9。
Plan B:先在school表中找出class字段值为9的行,再判断gender字段值是否为'Male'。
优化器分为两种:CBO基于代价的优化器、RBO基于规则的优化器,MySQL使用的是CBO。
CBO会从多个执行路径中选择一个"成本"最小的执行路径来作为执行计划。成本的具体计算是非常复杂的,简单的说,成本代表了MySQL根据统计信息(如索引,表,行)通过成本模型计算出来目标SQL对应的步骤的IO,CPU等消耗,也就是说统计信息的大小、成本模型的合理性影响着执行计划的选择。
如果使用的是预编译SQL,则经过一次编译,就能够多次运行,省去解析、优化的过程。
如果此时存在执行计划缓存,就可以直接使用已缓存的执行计划,跳过生成执行计划,加快查询SQL的速度。
四.执行器
执行器根据传入的执行计划完成整个查询,但首先会检查用户是否拥有对该表的操作权限,再根据表的引擎定义调用引擎接口去根据执行计划对表进行查询。
如果不存在过滤,MySQL将进行全表扫描,返回所有行。
如果存在过滤,根据条件过滤(若存在索引,且开启了索引下推,则交由存储引擎完成),符合则存储在结果集中,不符合则跳过,如此遍历到最后。
当有一条结果生成,其实就在开始准备向Client返回数据了,一旦整个查询的结果集被完整获取并存储在缓存中,MySQL 会一次性将整个结果集返回给Client,所以看起来就像是一次性发送的。
五.存储引擎
在MySQL5.6之后 新增了索引下推的功能:将执行器数据筛选的过程交由存储引擎 处理,减少了Server层(解析器预处理器、优化器、执行器)的负担,提高查询的效率,特别是在使用索引的时候,可以减少扫描的数据量,减少不必要的读取。
索引下推:在传统的查询流程中,MySQL通过索引检索符合条件的行,然后通过回表 操作获取实际的数据行。因为索引通常只存储了行的标识符(PRIMARY KEY/ID),而不是完整的行数据,所以才需要回表。而索引下推会将部分where子句中的条件下推到索引扫描过程中,在索引扫描的同时过滤,因为在索引扫描的时候还未读取整个行数据,且减少了回表的数量,所以特别是在大表和复杂查询中,能够显著提高查询的性能。
索引下推默认是开启的,也可以在系统变量中查看index_condition_pushdown的值是否为on。
sql
show variables like 'optimizer_switch'\G;
参考文章链接:
一条SQL语句在MySQL中执行过程全解析_本篇文章会分析下---个sql语句在mysql中的执行流程,包括sql的查询在mysql内部会怎-CSDN博客
MySQL进阶学习(一)----MySQL架构与SQL执行流程 - 掘金
MySQL教程2:从MySQL的逻辑架构看SQL查询语句是如何被执行的,了解连接管理、解析器、查询优化器、执行引擎,Server层和引擎层各自的作用 - 掘金
MySQL的SQL预处理(Prepared) - 海东潮 - 博客园