MySQL 的 Query 处理可以分为 Parse、Prepare(Resolve/Transform)、Optimize 和 Execute 几个阶段
Parse
词法扫描器将 SQL 语句字符串分解为 tokens,语法分析器将 tokens 组装成语法树的子树结构,并 Reduce 为基本查询结构,最终生成 SQL 语法解析数
MySQL 语法解析树结构如【MySQL·8.0·源码】MySQL 语法树结构
Prepare
Optimize
代价评估,table access method 选择,最优 join order 选择
MySQL table access method 部分可以阅读 【MySQL·8.0·源码】MySQL 表的扫描方式
Execute
查询执行处理
unique_ptr<RowIterator> iterator(new ...);
if (iterator->Init())
return true;
while (iterator->Read() == 0) {
...
}
先通过一个简单的单表索引查询所经过的重要函数,对各个阶段可能走过的重要函数有个大概印象,后序
会再通过不同的例子来说明各个函数的作用
Sql_cmd_dml::execute()
Sql_cmd_dml::prepare // Prepare
check_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 | v
Query_block::apply_local_transforms | /* transform 阶段 */
Query_block::simplify_joins | ^
lock_tables | |
v v
Query_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 v
Query_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 ...
...