# 58.1.采样方法支持函数

TSM handler函数返回一个palloc'dTsmRoutine包含指向下面描述的支持函数的指针的结构。大多数函数都是必需的,但有些是可选的,这些指针可以为NULL。

void
SampleScanGetSampleSize (PlannerInfo *root,
                         RelOptInfo *baserel,
                         List *paramexprs,
                         BlockNumber *pages,
                         double *tuples);

此函数在计划期间调用。它必须估计样本扫描期间将读取的关系页的数量,以及扫描将选择的元组的数量。(例如,可以通过估计采样分数,然后乘以baserel->pagesbaserel->tuples按此编号,确保将结果四舍五入为整数值。)这个参数列表中包含的表达式是表样本条款建议使用估计值表达式值()如果出于估算目的需要这些表达式的值,则尝试将其简化为常数;但是函数必须提供大小估计,即使它们不能减少,并且即使这些值看起来无效,它也不应该失败(记住,它们只是对运行时值的估计)。这个元组参数是输出。

void
InitSampleScan (SampleScanState *node,
                int eflags);

初始化以执行SampleScan计划节点。这在executor启动期间调用。在开始处理之前,它应该执行所需的任何初始化。这个样本扫描状态节点已创建,但其密苏里州字段为空。这个InitSampleScan函数可以调用采样方法所需的任何内部状态数据,并在节点->tsm_状态。有关要扫描的表的信息可通过样本扫描状态节点(但请注意node->ss。ss_扫描描述符尚未设置)。eflags包含描述此计划节点的执行器操作模式的标志位。

什么时候(仅适用于eflags和EXEC标志)如果为true,则不会实际执行扫描,因此此函数只应执行使节点状态对其有效所需的最小值解释EndSampleScan.

在这种情况下,可以忽略此函数(将指针设置为NULL)贝金森普尔斯坎必须执行采样方法所需的所有初始化。

void
BeginSampleScan (SampleScanState *node,
                 Datum *params,
                 int nparams,
                 uint32 seed);

开始执行采样扫描。在第一次尝试获取元组之前调用该函数,如果需要重新启动扫描,则可以再次调用该函数。有关要扫描的表的信息可以通过样本扫描状态节点(但请注意node->ss。ss_扫描描述符尚未设置)。这个params数组,长度NPAAMS,包含中提供的参数值表样本条款它们的数量和类型将在取样方法手册中指定参数类型列表,并且已被检查为不为空。种子包含用于采样方法中生成的任何随机数的种子;它要么是从可重复如果给出了一个值,或者随机的如果不是的话。

此功能可以调整字段节点->使用_bulkread节点->使用页面模式如果节点->使用_bulkread符合事实的,默认情况下,扫描将使用缓冲区访问策略,鼓励在使用后回收缓冲区。将此设置为错误的如果扫描只访问表格页面的一小部分。如果节点->使用页面模式真的,默认情况下,扫描将对每个访问页面上的所有元组执行一次可见性检查。将其设置为可能是合理的错误的如果扫描将只选择每个访问页面上元组的一小部分。这将导致执行更少的元组可见性检查,尽管每个检查都会更昂贵,因为它需要更多的锁定。

如果标注采样方式repeatable_across_scans,它必须能够在重新扫描期间选择与最初相同的元组集,这是一个新的调用开始样品扫描必须导致选择与以前相同的元组(如果表样参数和种子不会改变)。

BlockNumber
NextSampleBlock (SampleScanState *node, BlockNumber nblocks);

返回要扫描的下一页的块号,或无效块号如果没有要扫描的页面。

该函数可以省略(将指针设置为 NULL),在这种情况下,核心代码将执行整个关系的顺序扫描。这样的扫描可以使用同步扫描,因此采样方法不能假设关系页面在每次扫描中都以相同的顺序被访问。

OffsetNumber
NextSampleTuple (SampleScanState *node,
                 BlockNumber blockno,
                 OffsetNumber maxoffset);

返回要在指定页面上采样的下一个元组的偏移量,或无效偏移编号如果没有元组需要采样。最大偏移量是页面上使用的最大偏移量。

# 笔记

NextSampleTuple没有明确告知范围内的哪些偏移量1 .. 最大偏移量实际上包含有效的元组。这通常不是问题,因为核心代码忽略了对缺失或不可见元组进行采样的请求;这不应导致样本中的任何偏差。但是,如果需要,该功能可以使用节点-> 多胞胎检查它返回的元组中有多少是有效和可见的。

# 笔记

NextSampleTuple必须不是假使,假设块号与最近返回的页码相同下一个样品块称呼。它是由以前的一些人退回的下一个样品块调用,但允许核心代码调用下一个样品块在实际扫描页面之前,以支持预取。可以假设一旦给定页面的采样开始,连续NextSampleTuple调用都指向同一页面,直到无效偏移编号被退回。

void
EndSampleScan (SampleScanState *node);

结束扫描并释放资源。释放 palloc 的内存通常并不重要,但应该清理任何外部可见的资源。在不存在此类资源的常见情况下,可以省略此函数(将指针设置为 NULL)。