openGauss源码解析(148)
openGauss源码解析:执行器解析(42)
2. VecSort算子
VecSort算子用于缓存下层节点返回的所有结果元组并进行排序,对于结果元组较多时,会使用临时文件进行存储,并使用外排序进行排序操作。
VecSort算子对应的代码源文件是“vecsort.cpp”,VecSort算子对应的主要数据结构是VecSortState,继承于SortState。相应代码如下:
typedef struct VecSortState : public SortState {
VectorBatch* m_pCurrentBatch;
char* jitted_CompareMultiColumn;
char* jitted_CompareMultiColumn_TOPN;
} VecSortState;
VecSort算子的相应函数有:ExecInitVecSort(初始化节点)、ExecVecSort(执行节点)、ExecEndVecSort(退出节点)、ExecReScanVecSort(重置节点)。
ExecInitVecSort函数用于初始化VecSort算子。主要执行流程如下。
(1) 创建并初始化VecSortState执行节点。
(2) 分别调用“ExecInitResultTupleSlot(estate, &sort_state->ss.ps)”函数用于存储投影结果和“ExecInitScanTupleSlot(estate, &sort_state->ss)”函数用于初始化扫描元组槽。
(3) 调用“ExecAssignScanTypeFromOuterPlan(&sort_state->ss)”函数初始化元组类型,调用“ExecAssignResultTypeFromTL(&sort_stat->ss.ps,sort_stat->ss.ss_ScanTupleSlot->tts_tupleDescriptor->tdTableAmType)”函数初始化结果扫描描述符。
ExecVecSort函数是VecSort算子的主体函数。主要执行流程是:初次执行时,首先调用batchsort_begin_heap函数初始化元组缓存结构,之后循环执行从下层节点获取元组;调用sort_putbatch将获取的元组存放到缓存中;获取全部元组之后,调用batchsort_performsort进行排序;后续对VecSort算子的执行,调用batchsort_getbatch直接从缓存中获取一个元组。
ExecEndVecSort函数用于清理VecSort算子执行过程中使用的资源。主要执行流程是:首先调用ExecClearTuple函数依次清理“node->ss.ss_ScanTupleSlot”元组缓存和“node->ss.ps_ResultTupleSlot”排序后的元组缓存,之后调用batchsort_end函数释放用于元组排序的资源,最后调用“ExecEndNode(outerPlanState(node)) ”函数清理子计划节点。
ExecReScanVecSorts函数用于重新执行扫描计划,执行流程图如图33所示。主要执行流程是:
(1) 判断是否已经进行过排序;如没有执行过,则调用VecExecReScan函数重新扫描执行节点即可,反之则先判断子节点是否已经重新扫描。
(2) 如果子节点已经重新扫描,则调用ExecClearTuple函数清理已经排序的结果元组,调用batchsort_end函数清理“node->tuplesortstate”,调用VecExecReScan函数重新扫描执行节点;如果没有,则判断当前计划是否是“partition-wise join”并且需要切换分区。
(3)如果当前计划是“partition-wise join”并且需要切换分区,则同样需要调用batchstore_end函数和VecExecReScan函数进行重新扫描计划;否则只需要调用“batchstore_rescan(node->tuplesortstate)”。
ExecReScanVecSorts函数执行流程如图7-33所示。


图7-33 ExecReScanVecSort函数执行流程

浙公网安备 33010602011771号