mysql接收到sql格式的查询请求时,这里说的查询请求包括增删改查等,后面提到查询请求也是这个意思,收到后解析器会将文本格式的sql转化为sql解析树,供后续的优化器使用。优化器负责根据解析树制定查询计划并执行以检索查询所请求的数据记录。优化器的工作内容是选取表的连接顺序和读取记录的方法,如从索引中读取或扫描表以及要使用的键。目的是尽快交付查询结果。
解析器
解析器由两部分组成:句法扫描器,也叫词法扫描器和语法规则模块。句法扫描器将sql分解为多个token,token是不可分割的元素,如列名、select关键字等,每个令牌有一个类型如关键字、字符串、数字、操作符、函数等。然后语法规则模块根据token找到相应的语法规则组合。最后生成一棵树供优化器使用。
示例 :
解析器的两个目标:
1. 解析速度必须足够快
2. 生成的数据结构必须能够被优化器快速的访问
句法扫描器
使用gen_lex_hash工具生成的查找树查找token字符串对应的token类型,查找树第一层是长度散列,不同长度的字符串对应数组中的一个索引,第二层是首字母散列,不同的首字母对应数组中的一个索引,第三层是尾字母散列。通过一层层匹配最终定位到与token字符串相同的节点,从而获得该token字符串对应的类型等信息。
语法规则模块
使用gnu bison生成
解析树
用于存储每个可能的sql所包含的信息。解析树由LEX类型表示,lex是法律、规则的意思,下面主要看其两个重要的成员sql_command和select_lex。
sql_command表示查询的类型,是select update insert还是delete。
select_lex成员众多,主要的有 where从句 表列表 字段列表 优化器信息 对其他子查询的select_lex的交叉引用 order by group by等。下面主要看Item* where成员,其是where从句的根节点,优化器所需的大部分信息都从where从句获得。
Item类表示一个表达式树的各个节点,其可以表示运算如加减乘除 sql函数 逻辑运算符如and or 表字段 子查询返回的一行 以及能在where having groupby orderby中找到的任何元素。
Item中有多种val_开头的表达式,如返回int就是val_int(),优化器通过调用这些方法验证组合是否应该放到结果集。
示例
优化器
优化器算法基础
在mysql优化器算法中每个查询都是一系列的连接。首先连接器确定最佳的连接顺序,然后执行嵌套循环来实现连接。连接的本质是表子集的笛卡尔积。每个子集都是基于全表扫描、全索引扫描、一个单键或键集从表中读取,然后通过where从句的限制条件删除记录。成本通常与检查的记录组合数量成比例。查询优化分两部分:首先根据给定的顺序决定最佳访问路径(是全表扫描、还是索引扫描等),其次在最短时间内找到最佳连接顺序。
使用explain显示优化器的执行计划
示例:
连接顺序为customer -》order
customer表:用到了state索引,与常量匹配,使用了where过滤
order表:使用customer_id索引,与c.id匹配,只用到了索引没有回访记录。