mysql怎么执行sql mysql怎么执行存储过程

MySql中Sql的执行过程如果查询缓存没有命中,那么SQL请求会进入分析器,分析器是用来分辨SQL语句的执行目的,其执行过程大致分为两步:
表1 语法分析关键字然后再通过语法规则解析,判断输入的SQL 语句是否满足MySQL语法,并且生成图5的语法树 。由SQL语句生成的四个单词中,识别出两个关键字,分别是select 和from 。根据MySQL的语法Select 和 from之间对应的是fields 字段,下面应该挂接username;在from后面跟随的是Tables字段,其下挂接的是userinfo 。
优化器的作用是对SQL进行优化 , 生成最有的执行方案 。如图6所示 , 前面提到的SQL解析器通过语法分析和语法规则生成了SQL语法树 。这个语法树作为优化器的输入,而优化器(黄色的部分)包含了逻辑变换和代价优化两部分的内容 。在优化完成以后会生成SQL执行计划作为整个优化过程的输出,交给执行器在存储引擎上执行 。
所处的位置如上图所示 , 这节的重点在优化器中的逻辑变换和代价优化上 。
逻辑变换也就是在关系代数基础上进行变换 , 其目的是为了化简,同时保证SQL变化前后的结果一致,也就是逻辑变化并不会带来结果集的变化 。其主要包括以下几个方面:
这样讲概念或许有些抽象,通过图7 来看看逻辑变化如何在SQL中执行的吧 。
如图7所示 , 从上往下共有4个步骤:
1. 针对存在的SQL语句,首先通过“否定消除”,去掉条件判断中的“NOT” 。语句由原来的“or”转换成“and”,并且大于小于符号进行变号 。蓝色部分为修改前的SQL,红色是修改以后的SQL 。2. 等值传递,这一步很好理解分别降”t2.a=9” 和”t2.b=5”分别替换掉SQL中对应的值 。3. 接下来就是常量表达式计算,将“5+7”计算得到“12” 。4. 最后是常量表达式计算后的化简,将”9=10”化简为”true”带入到最终的SQL表达式中完成优化 。
代价优化是用来确定每个表,根据条件是否应用索引 , 应用哪个索引和确定多表连接的顺序等问题 。为了完成代价优化 , 需要找到一个代价最小的方案 。因此,优化器是通过基于代价的计算方法来决定如何执行查询的(Cost-based Optimization) 。简化的过程如下:
这里将配置操作的代价分为MySQL 服务层和MySQL 引擎层 , MySQL 服务层主要是定义CPU的代价,而MySQL 引擎层主要定义IO代价 。MySQL 5.7 引入了两个系统表mysql.server_cost和mysql.engine_cost来分别配置这两个层的代价 。如下:MySQL 服务层代价保存在表server_cost中,其具体内容如下:
由上可以看出创建临时表的代价是很高的,尤其是内部的myisam或innodb临时表 。MySQL 引擎层代价保存在表engine_cost中,其具体内容如下:
目前io_block_read_cost和memory_block_read_cost默认值均为1,实际生产中建议酌情调大memory_block_read_cost , 特别是对普通硬盘的场景 。MySQL会根据SQL查询生成的查询计划中对应的操作从上面两张代价表中查找对应的代价值,并且进行累加形成最终执行SQL计划的代价 。再将多种可能的执行计划进行比较,选取最小代价的计划执行 。
当分析器生成查询计划,并且经过优化器以后 , 就到了执行器 。执行器会选择执行计划开始执行 , 但在执行之前会校验请求用户是否拥有查询的权限,如果没有权限,就会返回错误信息 , 否则将会去调用MySQL引擎层的接口 , 执行对应的SQL语句并且返回结果 。例如SQL:“SELECT * FROM userinfo WHERE username = 'Tom';“假设 “username“ 字段没有设置索引,就会调用存储引擎从第一条开始查 , 如果碰到了用户名字是” Tom“, 就将结果集返回 , 没有查找到就查看下一行,重复上一步的操作 , 直到读完整个表或者找到对应的记录 。需要注意SQL语句的执行顺序并不是按照书写顺序来的 , 顺序的定义会在分析器中做好,一般是按照如下顺序:

推荐阅读