Query processing
MySQL 的 Query 处理可以分为 Parse、Prepare(Resolve/Transform)、Optimize 和 Execute 几个阶段
-
Parse
词法扫描器将 SQL 语句字符串分解为 tokens,语法分析器将 tokens 组装成语法树的子树结构,并 Reduce 为基本查询结构,最终生成 SQL 语法解析数MySQL 语法解析树结构如【MySQL·8.0·源码】MySQL 语法树结构
-
Prepare
- Resolve
语义检查
对象解析(schema名称、表名称、view 对象,将其解析为实际存储对象,并检查是否存在)
对子查询进行初步解析,尝试是否可以合并到外层 - Transform
逻辑改写转换(IN 转换为 semi-join,IN 转换为 EXISTS,ANY/ALL 改写)
Outer JOIN 到 Inner JOIN 的转换
条件谓词的 Transform
子查询的 Transform
- Resolve
-
Optimize
代价评估,table access method 选择,最优 join order 选择MySQL table access method 部分可以阅读 【MySQL·8.0·源码】MySQL 表的扫描方式
-
Execute
查询执行处理- MySQL 采用的执行模型为 Volcano 迭代模型
- MySQL 每个迭代器都有一个通用的迭代器接口,init()->read()
unique_ptr<RowIterator> iterator(new ...); if (iterator->Init())return true; while (iterator->Read() == 0) {... }
- JOIN 连接也是一个迭代器
- Nested Loop Join
- BKA Join
- Hash Join
主要函数
先通过一个简单的单表索引查询所经过的重要函数,对各个阶段可能走过的重要函数有个大概印象,后序
会再通过不同的例子来说明各个函数的作用
Sql_cmd_dml::execute()Sql_cmd_dml::prepare // Preparecheck_table_access ^open_tables_for_query |open_tables |open_and_process_table |open_table |Query_block::prepare | /* resolve 阶段 */Query_block::setup_tables | ^setup_natural_join_row_types | |Query_block::setup_wild | |setup_fields | |Query_block::setup_conds | |Query_block::setup_join_cond | vQuery_block::apply_local_transforms | /* transform 阶段 */Query_block::simplify_joins | ^lock_tables | |v vQuery_expression::optimize // optimize 阶段Query_block::optimize ^JOIN::optimize() |JOIN::make_join_plan |Optimize_table_order::choose_table_order|Optimize_table_order::greedy_search |make_join_query_block |JOIN::optimize_distinct_group_order |JOIN::test_skip_sort |reduce_cond_for_table |make_join_readinfo |setup_semijoin_dups_elimination |JOIN::make_tmp_tables_info |JOIN::push_to_engines vQuery_expression::execute // excute 阶段THD::send_result_metadata ^handler::ha_rnd_init |int ha_innobase::rnd_init |handler::ha_rnd_next |int ha_innobase::rnd_next |int ha_innobase::index_first |int ha_innobase::index_read ......