巅峰战队|详解一条查询select语句和更新update语句的执行流程( 二 )


巅峰战队|详解一条查询select语句和更新update语句的执行流程在这里插入图片描述
查询缓存连接上了之后 , 如果缓存是打开的 , 那么就会进入查询缓存阶段 , 可以通过如下命令查看缓存是否开启:
SHOW VARIABLES LIKE 'query_cache_type';
巅峰战队|详解一条查询select语句和更新update语句的执行流程在这里插入图片描述
我们可以看到 , 缓存默认是关闭的 。 这是因为MySQL的缓存使用条件非常苛刻 , 是通过一个大小写敏感的哈希值去匹配的 , 这样就是说一条查询语句哪怕只是有一个空格不一致 , 都会导致无法使用缓存 。 而且一旦表里面有一行数据变动了 , 那么关于这种表的所有缓存都会失效 。 所以一般我们都是不建议使用缓存 , MySQL最新的8.0版本已经将缓存模块去掉了 。
解析器和预处理器跳过了缓存模块之后 , 查询语句会进入解析器进行解析 。
词法解析和语法解析(Parser)这一步主要的工作就是检查sql语句的语法对不对 , 在这里 , 首先会把我们整个SQL语句打碎 , 比如:select name from test where id=1 , 就会被打散成select , name , from , test , where , id , = , 1 这8个字符 , 并且能识别出关键字和非关键字 , 然后根据sql语句生成一个数据结构 , 也叫做解析树(select_lex) , 如下图:
巅峰战队|详解一条查询select语句和更新update语句的执行流程在这里插入图片描述
预处理器(Preprocessor)经过了前面的词法和语法解析 , 那么至少我们一条sql语句的语法格式是满足要求了 , 接下来我们还需要做什么呢?自然是检查表名 , 列名以及其他一些信息等是不是真实存在的 , 预处理就是做一个表名和字段名等相关信息合法性的检测 。
查询优化器(Query Optimizer)经过上面的步骤 , 到这里就得到了一句有效的sql语句了 。 而对一个查询语句 , 尤其是复杂的多表查询语句 , 我们可以有很多种执行方式 , 每种执行方式的效率也不一样 , 所以这时候就需要查询优化器去选择一种它认为最高效的执行方式 。
查询优化器的目的就是根据解析树生成不同的执行计划(Execution Plan) , 然后选择一种最优的执行计划 , MySQL 里面使用的是基于开销(cost)的优化器 , 哪种执行计划开销最小 , 就选择哪种 。
我们可以通过变量Last_query_cost来查询开销:
SELECT * FROM test;show status like 'Last_query_cost';
巅峰战队|详解一条查询select语句和更新update语句的执行流程在这里插入图片描述
上图中展示的结果就表示MySQL认为SELECT * FROM test 查询语句需要做至少2个数据页的随机查找才能完成上面的查询 。 这个结果是通过一系列复杂的运算得到的 , 包括每个表或者索引的页面个数 , 索引的基数 , 索引和数据行的长度 , 索引分布的情况 。
优化器在评估成本的时候 , 不会考虑任何缓存的作用 , 而是假设读取任何数据都需要经过一次IO操作 。
优化器可以做哪些优化优化器可以替我们做很多优化 , 下面列举一些常用的优化: