MySQL源码解析之履行计划

  • MySQL履行计划介绍
  • MySQL履行计划代码概览
  • MySQL履行计划总结

一、MySQL履行计划介绍

在MySQL中,履行计划的实现是根据JOINQEP_TAB这两个目标。其中JOIN类表明一个查询句子块的优化和履行,每个select查询句子(即Query_block目标)在处理的时候,都会被当做JOIN目标,其界说在sql/sql_optimizer.h

QEP_TABQuery 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