一、解析器
Mysql解析器分为两部分:词法解析;语法解析。
词法解析:根据构词规则识别单词,可以使用lex或Flex等工具自动生成;
语法分析:将单词序列组合成各类语法短语,最后生成一个解析树,解析树是优化器依赖的数据结构。语法分析常用Bison工具自动处理。
下图是一个生成的解析树:(图中1.1、1.2、select2等类型都是SELECT_LEX;unit1等类型都是SELECT_UNIT类)
二、优化器
SQL的执行有两条主要的调用路径,一个是带UNION操作情况下的执行路径,大致如图上方所示;一个是单个SELECT的执行路径,大致如下方所示。
SELECT_LEX类中有成员join(类型为JOIN *),JOIN的操作对象是TABLE对象群(TABLE对象群被存于TABLE_LIST中)。
三、mysql_select
本文只跟踪一下mysql_select(),mysql_union()就不跟踪了。
注意:在调用mysql_select之前,会调用query_cache.store_query(thd, TABLE_LIST *all_tables),作用是register query in cache。
调用流程:
do_command----->dispatch_command-------->mysql_parse------>mysql_execute_command------>execute_sqlcom_select------>handle_select------->mysql_select
mysql_select会调用JOIN::prepare, JOIN::optimize, JOIN::exec.
1、JOIN::prepare
Check fields, find best join, do the select and output fields. mysql_select assumes that all tables are already opened.
2、JOIN::optimize
(1)其中会调用simplify_joins(JOIN *join, List<TABLE_LIST> *join_list, COND *conds, bool top):replace outer joins by inner joins whenever it's possible. 如SELECT * FROM t1 LEFT JOIN t2 ON t2.a=t1.a WHERE t2.b < 5会被转化为SELECT * FROM t1 INNER JOIN t2 ON t2.a=t1.a WHERE t2.b < 5,进一步为SELECT * FROM t1, t2 ON t2.a=t1.a WHERE t2.b < 5 AND t2.a=t1.a。
这篇文章对各种JOIN做了比较好的展示:http://blog.youkuaiyun.com/taylor_tao/article/details/7068511
(2)之后会调用conds= optimize_cond(this, conds, join_list, &cond_value),conds应该是where条件,前面讲outer join转化为inner join更利于where的优化
(3)make_join_statistics():Calculate the best possible join and initialize the join structure.
3、JOIN::exec:Exec select.
最后回到dispatch_command()中,会调用thd->protocol->end_statement()将获得的查询结果发送到客户端。
注:由于表结构、缓存等尚未研究,所以目前只能对优化器作一个宏观的认识,还有很多问题:如查询缓存,最优join的选择,返回结果的数据结构等。