《MySQL 8.0.22执行器源码分析(2)解读函数 ExecuteIteratorQuery》
函数代码
bool SELECT_LEX_UNIT::ExecuteIteratorQuery(THD *thd) {THD_STAGE_INFO(thd, stage_executing);DEBUG_SYNC(thd, "before_join_exec");Opt_trace_context *const trace = &thd->opt_trace;Opt_trace_object trace_wrapper(trace);Opt_trace_object trace_exec(trace, "join_execution");if (is_simple()) {trace_exec.add_select_number(first_select()->select_number);}Opt_trace_array trace_steps(trace, "steps");if (ClearForExecution(thd)) {return true;}mem_root_deque<Item *> *fields = get_field_list();Query_result *query_result = this->query_result();DBUG_ASSERT(query_result != nullptr);if (query_result->start_execution(thd)) return true;if (query_result->send_result_set_metadata(thd, *fields, Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF)) {return true;}set_executed();// Hand over the query to the secondary engine if needed.if (first_select()->join->override_executor_func != nullptr) {thd->current_found_rows = 0;for (SELECT_LEX *select = first_select(); select != nullptr;select = select->next_select()) {if (select->join->override_executor_func(select->join)) {return true;}thd->current_found_rows += select->join->send_records;}const bool calc_found_rows =(first_select()->active_options() & OPTION_FOUND_ROWS);if (!calc_found_rows) {// This is for backwards compatibility reasons only;// we have documented that without SQL_CALC_FOUND_ROWS,// we return the actual number of rows returned.thd->current_found_rows =std::min(thd->current_found_rows, select_limit_cnt);}return query_result->send_eof(thd);}if (item) {item->reset_value_registration();if (item->assigned()) {item->assigned(false); // Prepare for re-execution of this unititem->reset();}}// We need to accumulate in the first join's send_records as long as// we support SQL_CALC_FOUND_ROWS, since LimitOffsetIterator will use it// for reporting rows skipped by OFFSET or LIMIT. When we get rid of// SQL_CALC_FOUND_ROWS, we can use a local variable here instead.ha_rows *send_records_ptr;if (fake_select_lex != nullptr) {// UNION with LIMIT: found_rows() applies to the outermost block.// LimitOffsetIterator will write skipped OFFSET rows into the// fake_select_lex's send_records, so use that.send_records_ptr = &fake_select_lex->join->send_records;} else if (is_simple()) {// Not an UNION: found_rows() applies to the join.// LimitOffsetIterator will write skipped OFFSET rows into the JOIN's// send_records, so use that.send_records_ptr = &first_select()->join->send_records;} else {// UNION, but without a fake_select_lex (may or may not have a// LIMIT): found_rows() applies to the outermost block. See// SELECT_LEX_UNIT::send_records for more information.send_records_ptr = &send_records;}*send_records_ptr = 0;thd->get_stmt_da()->reset_current_row_for_condition();{auto join_cleanup = create_scope_guard([this, thd] {for (SELECT_LEX *sl = first_select(); sl; sl = sl->next_select()) {JOIN *join = sl->join;join->join_free();thd->inc_examined_row_count(join->examined_rows);}if (fake_select_lex != nullptr) {thd->inc_examined_row_count(fake_select_lex->join->examined_rows);}});if (m_root_iterator->Init()) {return true;}PFSBatchMode pfs_batch_mode(m_root_iterator.get());for (;;) {int error = m_root_iterator->Read();DBUG_EXECUTE_IF("bug13822652_1", thd->killed = THD::KILL_QUERY;);if (error > 0 || thd->is_error()) // Fatal errorreturn true;else if (error < 0)break;else if (thd->killed) // Aborted by user{thd->send_kill_message();return true;}++*send_records_ptr;if (query_result->send_data(thd, *fields)) {return true;}thd->get_stmt_da()->inc_current_row_for_condition();}// NOTE: join_cleanup must be done before we send EOF, so that we get the// row counts right.}thd->current_found_rows = *send_records_ptr;return query_result->send_eof(thd);
}
函数过程浅析
1、is_simple()函数用来判断一个查询表达式是否有union或者多级order,如果没有说明这个查询语句简单。就执行add_select_number
,TODO
2、运行ClearForExecution
函数。
在初始化root迭代器之前,把之前的执行迭代器的数据清除。
3、运行get_field_list()
,获取查询表达式的字段列表,并将所有字段都放到一个deque中,即mem_root_deque<Item*>
;对于查询块的并集,返回在准备期间生成的字段列表,对于单个查询块,尽可能返回字段列表。
4、运行start_execution
,准备执行查询表达式或DML查询。
5、接下来的一些操作与第二引擎有关,关于该引擎见https://www.h5w3.com/123061.html
总结一下就是:Secondary Engine实际上是MySQL sever上同时支持两个存储引擎,把一部分主引擎上的数据,在Secondary Engine上也保存一份,然后查询的时候会根据优化器的的选择决定在哪个引擎上处理数据。
我们这里先不看这一部分
6、如果该查询用于子查询,那么重新reset,指向子查询。
7、接下来是对于复杂句以及简单句的不同处理,从而给send_records_ptr
赋值。
函数对于这个情况的解释如下:
We need to accumulate in the first join's send_records as long aswe support SQL_CALC_FOUND_ROWS, since LimitOffsetIterator will use itfor reporting rows skipped by OFFSET or LIMIT. When we get rid ofSQL_CALC_FOUND_ROWS, we can use a local variable here instead.
情况一:如果该查询块具有UNION或者多级的ORDER BY/LIMIT的话
UNION with LIMIT的话,found_rows()
用于最外层
LimitOffsetIterator
跳过偏移量行写入send_records
情况二:如果是个简单句的话
found_rows()
直接用到join上。
LimitOffsetIterator
跳过偏移量行写入send_records
情况三:如果是UNION,但是没有LIMIT
found_rows()
用于最外层。
8、重置计数器
9、接下来是一个对查询块遍历,逐个释放内存的操作,用以增加并发性并减少内存消耗。
10、初始化根迭代器
11、然后for循环,从根迭代器一直到引擎的handler,调用读取数据。如果出错就直接返回。
如果收到kill信号,也返回。
在循环中对send_records_ptr
进行累加。
行计数器++,指向下一行。
12、将send_records_ptr
赋值给该线程的current_found_rows
《MySQL 8.0.22执行器源码分析(2)解读函数 ExecuteIteratorQuery》相关推荐
- ComeFuture英伽学院——2020年 全国大学生英语竞赛【C类初赛真题解析】(持续更新)
视频:ComeFuture英伽学院--2019年 全国大学生英语竞赛[C类初赛真题解析]大小作文--详细解析 课件:[课件]2019年大学生英语竞赛C类初赛.pdf 视频:2020年全国大学生英语竞赛 ...
- ComeFuture英伽学院——2019年 全国大学生英语竞赛【C类初赛真题解析】大小作文——详细解析
视频:ComeFuture英伽学院--2019年 全国大学生英语竞赛[C类初赛真题解析]大小作文--详细解析 课件:[课件]2019年大学生英语竞赛C类初赛.pdf 视频:2020年全国大学生英语竞赛 ...
- 信息学奥赛真题解析(玩具谜题)
玩具谜题(2016年信息学奥赛提高组真题) 题目描述 小南有一套可爱的玩具小人, 它们各有不同的职业.有一天, 这些玩具小人把小南的眼镜藏了起来.小南发现玩具小人们围成了一个圈,它们有的面朝圈内,有的 ...
- 信息学奥赛之初赛 第1轮 讲解(01-08课)
信息学奥赛之初赛讲解 01 计算机概述 系统基本结构 信息学奥赛之初赛讲解 01 计算机概述 系统基本结构_哔哩哔哩_bilibili 信息学奥赛之初赛讲解 02 软件系统 计算机语言 进制转换 信息 ...
- 信息学奥赛一本通习题答案(五)
最近在给小学生做C++的入门培训,用的教程是信息学奥赛一本通,刷题网址 http://ybt.ssoier.cn:8088/index.php 现将部分习题的答案放在博客上,希望能给其他有需要的人带来 ...
- 信息学奥赛一本通习题答案(三)
最近在给小学生做C++的入门培训,用的教程是信息学奥赛一本通,刷题网址 http://ybt.ssoier.cn:8088/index.php 现将部分习题的答案放在博客上,希望能给其他有需要的人带来 ...
- 信息学奥赛一本通 提高篇 第六部分 数学基础 相关的真题
第1章 快速幂 1875:[13NOIP提高组]转圈游戏 信息学奥赛一本通(C++版)在线评测系统 第2 章 素数 第 3 章 约数 第 4 章 同余问题 第 5 章 矩阵乘法 第 6 章 ...
- 信息学奥赛一本通题目代码(非题库)
为了完善自己学c++,很多人都去读相关文献,就比如<信息学奥赛一本通>,可又对题目无从下手,从今天开始,我将把书上的题目一 一的解析下来,可以做参考,如果有错,可以告诉我,将在下次解析里重 ...
- 信息学奥赛一本通(C++版) 刷题 记录
总目录详见:https://blog.csdn.net/mrcrack/article/details/86501716 信息学奥赛一本通(C++版) 刷题 记录 http://ybt.ssoier. ...
- 最近公共祖先三种算法详解 + 模板题 建议新手收藏 例题: 信息学奥赛一本通 祖孙询问 距离
首先什么是最近公共祖先?? 如图:红色节点的祖先为红色的1, 2, 3. 绿色节点的祖先为绿色的1, 2, 3, 4. 他们的最近公共祖先即他们最先相交的地方,如在上图中黄色的点就是他们的最近公共祖先 ...
最新文章
- AI强势来袭,锁上手机就真的安全了吗?
- Delphi 使用双缓冲解决图片切换时的闪烁问题 good
- 面向过程与面向对象引入三大特性事务
- maven spring profile 协同
- 全程图解交换机和路由器的应用
- jmeter 压测 RabbitMQ_单机
- Mike Krueger 加入Mono团队
- 二阶齐次线性微分方程的通解公式_高数大结局二阶常系数非线性齐次方程
- matlab 类型转换(类型判断)
- BLS数字签名算法介绍及拓展
- Vray2.0材质手册
- 四元式的翻译以及寄存器分配
- 雅虎邮箱(yahoo):应用程序专用密码登录
- Notion、印象笔记、Roam research…不知道笔记系统构建方式!怎么能选到对的笔记应用?
- java即时通讯im聊天源码,dubbo即时通讯im聊天源码,netty即时通讯im聊天源码,springboot即时通讯im聊天源码
- 一图掌握ISACA五大资格证书体系
- 年终盘点一 | 云原生的 2022 年:降本提效、全面 Serverless 化
- 【问题记录】js 更改数组中某字段名
- linux编译动态库未定义,GCC链接库的一个坑:动态库存在却提示未定义动态库的函数...
- vs2008与vss2005用后感
热门文章
- 程序员养家活口接私活必备网站(顺便用技术改变世界)
- java 时间戳 星期几_java自定义获取星期几、几点、几分。
- java 获取服务器网络名_java-siger java使用siger 获取服务器硬件信息(CPU 内存 网络 io等) - 下载 - 搜珍网...
- 模态对话框和全选反选
- js正则验证方法大全
- 响应式框架Bootstrap栅格系统
- Laravel 不同环境加载不同的.env文件
- html笔记(四)弹性盒+响应式
- 我的GMAIL下蛋了,要的请留下姓,名和email!!
- 【转】 差分约束系统详解(转化为最短路) (概念)