MySQL源码解析之履行计划
- MySQL履行计划介绍
- MySQL履行计划代码概览
- MySQL履行计划总结
一、MySQL履行计划介绍
在MySQL中,履行计划的实现是根据JOIN
和QEP_TAB
这两个目标。其中JOIN类表明一个查询句子块的优化和履行,每个select查询句子(即Query_block目标)在处理的时候,都会被当做JOIN目标,其界说在sql/sql_optimizer.h
。
QEP_TAB
是Query Execution Plan Table
的缩写,这里的表Table目标首要包含物化表、暂时表、派生表、常量表等。JOIN::optimize()
是优化履行器的统一入口,在这里会把一个查询句子块Query_block
终究优化成QEP_TAB
。
在MySQL-8.0.22版别之后,又引进拜访方法AccessPath
和履行迭代器Iterator
目标,再结合JOIN和QEP_TAB目标,终究得到整个解析计划的履行途径。
二、MySQL履行计划代码概览
本文首要根据MySQL-8.0.25版别,进行说明。
优化器的入口函数:bool JOIN::optimize()
,对应代码文件sql/sql_optimizer.cc
。
// 首要功能是把一个查询块Query_block优化成一个QEP_TAB,得到AccessPath
bool JOIN::optimize() {
...
// 下面首要是为了能够借助INFORMATION_SCHEMA.OPTIMIZER_TRACE表,盯梢优化器的履行状况和履行步骤
Opt_trace_context *const trace = &thd->opt_trace;
Opt_trace_object trace_wrapper(trace);
Opt_trace_object trace_optimize(trace, "join_optimization");
trace_optimize.add_select_number(Query_block->select_number);
Opt_trace_array trace_steps(trace, "steps");
...
// 窗口函数装置优化
if (has_windows && Window::setup_windows2(thd, m_windows))
...
// 拷贝Query_block上的条件副本到JOIN结构相关的成员目标,为后续优化做准备
if (Query_block->get_optimizable_conditions(thd, &where_cond, &having_cond))
...
// 核算抽象语法树中的叶节点表,其中leaf_tables是在Query_block::setup_tables中进行装置
tables_list = Query_block->leaf_tables;
...
// 分区裁剪
if (Query_block->partitioned_table_count && prune_table_partitions()) {
...
// 测验把聚合函数COUNT()、MIN()、MAX()对应的值,替换成常量
if (optimize_aggregated_query(thd, Query_block, *fields, where_cond,
&outcome)) {
...
// 选用超图算法生成履行计划,注意超图算法经过set optimizer_switch="hypergraph_optimizer=on"方法启用
if (thd->lex->using_hypergraph_optimizer) {
FindBestQueryPlan(thd, Query_block, /*trace=*/nullptr);
// 如果Join优化器是超图算法,处理完毕直接回来
return false;
}
...
下面代码首要触及Join优化器衔接方法为左深树的状况,首要用到join_tab
数组来进行组织相关
根据价值核算表的衔接方法,中心函数make_join_plan()
,实现非常复杂。比较要害的函数是bool Optimize_table_order::choose_table_order()
其首要思想是经过贪婪查找Optimize_table_order::greedy_search
,根据最小的衔接价值,进行有限的穷举查找(细节参阅Optimize_table_order::best_extension_by_limited_search)
终究找到近似最优解的衔接排列组合
if (make_join_plan()) {
...
// 句子块谓词条件下推,提高过滤功能
if (make_join_Query_block(this, where_cond)) {
...
// 优化order by/distinct句子
if (optimize_distinct_group_order()) return true;
...
// 分配QEP_TAB数组
if (alloc_qep(tables)) return (error = 1); /* purecov: inspected */
...
// 履行计划细化,优化子查询和半衔接的状况,具体战略能够参阅mariadb的文档:
// https:// mariadb.com/kb/en/optimization-strategies/
// 要害代码是setup_semijoin_dups_elimination,首要对半衔接相关的战略进行装置
if (make_join_readinfo(this, no_jbuf_after))
...
// 为处理group by/order by创立拓荒暂时表空间
if (make_tmp_tables_info()) return true;
...
// 生成拜访方法AccessPath,供后续迭代器Iterator拜访运用
create_access_paths();
...
return false;
}
三、MySQL履行计划总结
MySQL的履行计划是整个数据库最中心的模块,其代码也在不断地迭代更新进程中。履行计划中优化器的好坏和背面的查找战略、数学模型严密相关。MySQL支持的查找战略有穷举查找、贪婪查找,对应的Join优化器有左深树算法和超图算法,整个优化进程首要是根据CBO战略进行优化。
履行计划运转的进程,实际上便是一个动态规划的进程。这个进程的好坏,快慢决议了MySQL和干流商业数据库的距离。只要深化地了解MySQL优化器的运转原理,才干帮助咱们活跃有效地探索更高功能优化的或许。
最终因为笔者知识水平有限,遗漏之处,还望指正。
Enjoy GreatSQL :)
文章推荐:
面向金融级使用的GreatSQL正式开源
Changes in GreatSQL 8.0.25 (2021-8-18)
MGR及GreatSQL资源汇总
GreatSQL MGR FAQ
在Linux下源码编译装置GreatSQL/MySQL
关于 GreatSQL
GreatSQL是由万里数据库保护的MySQL分支,专注于提高MGR可靠性及功能,支持InnoDB并行查询特性,是适用于金融级使用的MySQL分支版别。
Gitee:
gitee.com/GreatSQL/Gr…
GitHub:
github.com/GreatSQL/Gr…
Bilibili:
space.bilibili.com/1363850082/…
微信&QQ群:
QQ群:533341697
微信群:可查找增加GreatSQL社区帮手
微信老友,发送验证信息“加群”加入GreatSQL/MGR沟通微信群
GreatSQL社区帮手:wanlidbc