《MySQL 8.0.22执行器源码分析(1)——execute iterator一些记录》

946 阅读4分钟

目录

一条语句的函数调用栈顺序

记录了函数语句从服务器main函数到执行器之前的一些具体调用,5.几版本到8.0.22版本,这里的调用顺序并没有多大变化
在这里插入图片描述
注意这里是接着上面的2、在这里插入图片描述
处理完之后,开始返回,返回到之前的case
在这里插入图片描述
按照网上代码版本接下来的调用顺序应该是这样的:这里的JOIN::exec()do_select我没有在8.0代码中找到,就直接跳过这两个函数吧。

在这里插入图片描述

8.0使用迭代器模式改进executor

在文章cloud.tencent.com/developer/a…中说道:
MySQL8.0对执行器进行了改进,创建一个新的用于迭代访问记录的API,它足够通用,可以替换MySQL中所有原有的记录迭代器,并逐步替代掉原有的执行器。
这是之前的执行器接口:
在这里插入图片描述
这是现在的:
在这里插入图片描述
该文章列出了一些迭代器类型:

TableScanIterator:顺序扫描,调用存储引擎接口ha_rnd_next获取一行记录。
IndexScanIterator:全量索引扫描,根据扫描顺序,分别调用ha_index_next或者ha_index_prev来获取一行记录。
IndexRangeScanIterator:范围索引扫描,包装了下QUICK_SELECT_I,调用QUICK_SELECT_I::get_next来获取一行记录。
SortingIterator:对另一个迭代器输出进行排序。
SortBufferIterator:从缓冲区读取已经排好序的结果集,(主要给SortingIterator调用)
SortBufferIndirectIterator:从缓冲区读取行ID然后从表中读取对应的行(由SortingIterator和某些形式的unique操作使用)
SortFileIterator:从文件中读取已经排好序的结果集(主要给SortingIterator调用)
SortFileIndirectIterator:从文件读取行ID然后从表中读取对应的行(由SortingIterator和某些形式的unique操作使用)
RefIterator:从连接右表中读取指定key的行。
RefOrNullIterator:从连接右表中读取指定key或者为NULL的行。
EQRefIterator:使用唯一key来从连接的右表中读取行。
ConstIterator:从一个只可能匹配出一行的表(Const Table)中读取一行数据。
FullTextSearchIterator:使用全文检索索引读取一行数据。
DynamicRangeIterator:为每一行调用范围优化器,然后根据需要包装QUICK_SELECT_I或表扫描。
PushedJoinRefIterator:读取已下推到NDB的连接的输出。
FilterIterator: 读取一系列行,输出符合条件的行,用来实现WHERE/HAVING。
LimitOffsetIterator: 从offset开始读取行,直到满足limit限制,用来实现LIMIT/OFFSET。
AggregateIterator: 实现聚集函数并且如果需要的话进行分组操作。
NestedLoopiterator: 使用嵌套循环算法连接两个迭代器(内连接,外连接或反连接)。
MaterializeIterator: 从另一个迭代器读取结果,并放入临时表,然后读取临时表记录。
FakeSingleRowIterator: 返回单行,然后结束。 仅在某些使用const表情况下才使用(例如只有const表,仍然需要一个迭代器来读取该单行)

下面是我对mysql语句
use table;debug时发现的迭代器调用顺序:
不知道解读是否正确。
在这里插入图片描述
之后就是将结果排序:
在这里插入图片描述

int handler::ha_rnd_next(uchar *buf)

dev.mysql.com/doc/dev/mys…
在这里插入图片描述

int TableScanIterator::Read()

dev.mysql.com/doc/dev/mys…
在这里插入图片描述

int FilterIterator :: Read()

一个迭代器,它接收一行流,并且仅通过那些满足某些条件(即条件的结果为true)的行。

dev.mysql.com/doc/dev/mys…
在这里插入图片描述

int HashJoinIterator::Read()

dev.mysql.com/doc/dev/mys…

在这里插入图片描述

int NestedLoopIterator :: Read()

一个简单的嵌套循环连接,接受两个迭代器(左/外和右/内)并将他们连接到一起。这可能会多次扫描内部迭代器。迭代器用作状态机,其中状态记录我们是否需要读取新的外部行,以及是否从内部迭代器中看到任何行(如果没有,则外部联接需要合成新的行)

dev.mysql.com/doc/dev/mys…
在这里插入图片描述

int StreamingIterator::Read ()

dev.mysql.com/doc/dev/mys…

StreamingIterator的每个Read()只会将调用转给子查询迭代器,并执行从一组字段到另一组的所需复制。它用于优化程序设置的实现的时间。

It is used for when the optimizer would normally set up a materialization, but you don't actually need one, ie. you don't want to read the rows multiple times after writing them, and you don't want to access them by index (only a single table scan). It also takes care of setting the NULL row flag on the temporary table.

这段英文没读懂。。。
在这里插入图片描述

ha_rows read_all_rows

读取所有行,并将它们写入一个临时文件(如果我们在排序缓冲区中空间不足)。

保证所有产生的序列都是非空的。返回的是成功记录的记录数

dev.mysql.com/doc/dev/mys…
在这里插入图片描述

回顾迭代器模式

迭代器模式:提供一种方法顺序访问一个聚合对象中各个元素,而不暴露该对象的内部表示。

当我们需要访问一个聚集对象,而且不管这些对象是什么都需要遍历的时候,就应该考虑用迭代器模式。

(针对不同对象)

当我们对聚集有多种方式遍历时,可以考虑用迭代器模式。 (针对不同遍历方式,如从前往后、从后往前)

为遍历不同的聚集结构提供统一接口。

关于MySQL8.0版本的迭代器的作用在后面的笔记继续介绍。