《MySQL 8.0.22执行器源码分析(3.1)关于RowIterator》

本文详细介绍了数据库中的RowIterator,它是一个用于按指定访问方式读取单个表的迭代器,支持索引读取、扫描等操作,并缓存数据。RowIterator包括Init()初始化、Read()读取行、SetNullRowFlag()设置空行标志、UnlockRow()解锁行等方法。在特定的查询场景中,如SELECT FOR UPDATE,UnlockRow()用于释放行锁。此外,StartPSIBatchMode()和EndPSIBatchModeIfStarted()用于性能模式批处理,以减少开销。RowIterator在联接查询中起到关键作用,可用于排序和其他迭代器的组合。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

RowIterator

使用选定的访问方法读取单个表的上下文:索引读取,扫描等,缓存的使用等。
它主要是用作接口,但也包含一些私有成员函数,这些函数对于许多实现都是有用的,例如错误处理。
RowIterator是一个简单的迭代器。您对其进行初始化,然后一次读取一个记录,直到Read()返回EOF。如果需要,RowIterator可以从其他Iterators读取数据,例如SortingIterator,它从另一个RowIterator接收记录并对其进行排序。
抽象并不完全紧密。特别是,它仍然留给TABLE一些细节,例如要读取的列(read_set)。这意味着可能很难对两个表的联接进行排序。

使用方法:

unique_ptr<RowIterator> iterator(new ...);
if (iterator->Init())
  return true;
while (iterator->Read() == 0) {
  ...
}

Init()

初始化或重新初始化迭代器。
在尝试Read()之前,必须始终调用Init()(但是Init()并不意味着Read())。
您可以多次调用Init();随后的调用将使迭代器倒回(或重新定位,具体取决于迭代器是否采用TABLE_REF),并允许您重新读取记录。

Read()

读一行。
该行数据实际上不是从函数返回的;它被放在表的记录缓冲区中(如果有连接,则放在表中),即table-> records [0]。

SetNullRowFlag()

将当前行缓冲区标记为包含或不包含NULL行,这样,如果您从中读取并且标志为true,则无论缓冲区中实际上有什么(通常是一些旧的剩余行),您都只会得到NULL。
当迭代器没有产生任何行并且我们需要产生一个NULL补充行时,它用于外部联接。Init()或Read()不一定会重置此标志,因此,如果您将其设置为true,请确保在需要时也将其设置为false。
注意,可以在不首先调用Init()的情况下调用它。

UnlockRow()

在一些特定的查询中,比如SELECT FOR UPDATE, UPDATE or DELETE查询,正在读取的行将在上面上锁。这意味着锁的设置取决于优化器是否选择了一个表扫描或者使用索引。
但是在某些事务隔离级别下(读取或提交),当且仅当行因为WHERE这个谓词失败,只有返回的行受到保护,那些没有返回的行就不会受到保护了。
所以如果Read()返回一行数据,如果不使用它,就应该Read()之后调用UnlockRow(),它将允许存储引擎在这种情况下释放行锁。

StartPSIBatchMode()

启动性能模式批处理模式。
PFS批处理模式可以减轻性能模式的开销,该性能模式通常应用于整个联接的最内表。
如果在扫描表之前先启动它,然后再结束它,则整个处理程序调用集将作为一组,并且成本将平均分配。这样可以减少计时器开销。
如果启动PFS批处理模式,则还必须注意在扫描结束时以一种另一种方式结束它。请注意,即使查询突然结束(达到LIMIT或者发生错误),也必须结束它。最简单的解决方法就是在扫描结束时在根迭代器上简单调用EndPSIBatchModeIfStarted()。
开始批处理和结束的规则是:
1、如果迭代器只有一个子类,则将所有StartPSIBatchMode()的调用转发给它。
2、如果驱动迭代器(使用for循环或者类似的方法读取行),需要使用PFSBatchMode
3、如果迭代器有多个子类,忽略StartPSIBatchMode()的调用,并且根据需要自行处理批处理模式
所以,在扫描单个表时,通常会为该表激活批处理模式,因为我们在根迭代器上调用该函数,并且一直向下传入表迭代器。但是调用后,该调用将被忽略,并且迭代器需要根据需要自行激活批处理模式。

EndPSIBatchModeIfStarted()

结束性能模式批处理模式
具有子级的迭代器(复合迭代器)必须将该函数调用转发给所有子迭代器。这样可以确保在对根迭代器进行这样的调用之后,所有处理程序都退出批处理模式。

real_iterator()

如果该迭代器包装了其他迭代器,需要将该迭代器向下转换为特定的迭代器类型。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

拾牙慧者

欢迎请作者喝奶茶

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值