讲述MySQL解析器与MySQL优化器的工作原理
MySQL解析器
MySQL解析器由两部分组成:句法扫描器和语法规则模块。语法扫描器讲整个查询分解为多个令牌(一些不可分割的元素,列如列名称),同时语法规则模块找到一个SQL语法规则组合,该组合产生这一序列,并执行与这些规则相关的代码。最后产生一棵解析树,现在优化器可以使用。
设想服务器收到下列查询:
select count(*),state from table_name group by state
这条SQL语句就会通过句法扫描器检查查询字符流,将其分解为令牌,然后识别每个令牌。如下:
select count ( * ) , state from table_name group by state
每个令牌都有一个类型,列如一个关键字,一个字符串,一个数字,一个操作符或一个函数名称。语法规则模块安装一系列规则与名片六相应匹配,然后找出正确的规则,而上面的SQL是select 规则(sql/sql_yacc.yy) 他相应地初始化解析树结构。
MySQL会通过sql/gen_lex_hash.cc 生成有效的关键字查询散列,然后通过扫描器sql/sql_lex.cc讲每个名片标记为一个关键字,一个函数名称,大量特定类型或一些在语法规则中具有某种意义的特殊符号,然后这些内容通过解析器根据语法规则创建对应的解析树。
(解析树主要是是lex类型对象代表,在sql/sql_lex.h中有定义 成员很多 比如:enum_sql_command sql_command 它显示我们正在执行的SQL查询类型,是 select,update,delete,insert还是其他类型)
MySQL优化器
MySQL优化器是一个数据库软件非常核心的功能,虽然说起来只是简单的几句话,单在MySQL内部,优化器实际上经过了很多复杂的运算分析,才得出的执行计划。对于优化器结合于后面的知识点涉及讲解。
优化器接收到解析器返回的解析树的内容然后会做如下几件事情(因为优化器的内容过多暂时可以先了解做的操作即可)
MySQL优化器具有几个重要功能
确定使用哪个键从表中获取记录,并选择最合适该表的建。
( join)针对每个表确定扫描标识符比读取建更好,如果有很多记录与建值匹配,则建的优点下降,而表扫描速度更快。( join)当查询中出现一个以上的表示,确定表的连接顺序
重写where从句,以删除死代码,减少不必要的计算,尽可能更改限制条件,以便为键使用开辟道路
( join)从链接中删除未使用的表
确定是否能将键用于order by 和 group by
( join)是这是用一个内部连接替换一个外部连接
( join)试着简化子查询,并决定其结果的高速缓存程度( join)合并试图(扩大视图引用,使其成为一个宏)
总结:
总的来说当客户端向MySQL请求一条query命令解析器模块完成请求分类,区别出是select并转发给优化器时,优化器会根据相应的规则对于query进行优化,处理掉一些常量表达式的预算,直接换掉常量值。并对query中的查询条件进行简化和转换,如去掉一些无用或显而意见的条件、结构调整等。然后分析query中的Hint(类似于标识)信息,如果有hint就会执行query的计划,没有就会读取设计对象的统计信息,根据query进行写相应的计算分析,然后再得出最后的计划。