openGauss的BatchStore和Batchsortstate为什么仅ForwardScanDirection取数据

2024年 5月 20日 47.3k 0

openGauss - 内核原理 - BatchStore和Batchsortstate为什么仅ForwardScanDirection取数据

openGauss的普通执行引起从Tuplestorestate(物化)和Tuplesortstate(排序)取数据时,会有方向,即ForwardScanDirection:从前向后依次取;BackwardScanDirection:从后向前依次取。但是,在向量化执行引擎中却仅支持ForwardScanDirection。难道向量化执行引擎不支持向后取batch,还是有bug?

1、扫描方向

扫描方向支持以下三种:

    typedef enum ScanDirection {
    BackwardScanDirection = -1,//从后向前
    NoMovementScanDirection = 0,//不执行扫描操作
    ForwardScanDirection = 1//从前向后
    } ScanDirection;

    standard_ExecutorRun函数中:当然这里仅展示普通查询的函数

    openGauss的BatchStore和Batchsortstate为什么仅ForwardScanDirection取数据-12、执行器三步曲

    查询执行器执行一个SQL时会以一个Portal作为输出数据,存放了与执行该SQL语句相关的所有信息,包括查询树、计划树、执行状态等。作为执行器的门户,所有的SQL语句执行都从一个选择好执行策略的Portal开始,经历Portal Start、PortalRun、PortalDrop三个过程。

    openGauss的BatchStore和Batchsortstate为什么仅ForwardScanDirection取数据-2

    PortalStart遍历整个计划树,挖出Portal的初始化。算子的初始化函数命名为“ExecInit+算子名”。初始化函数会先根据对应的Plan结构初始化一个对应的PlanState结构。整个结构是执行过程中的核心数据结构,包含了执行过程中需要的一些数据存储空间和执行信息:

    1)调用ChoosePortalStrategy选择执行策略

    2)PORTAL_ONE_SELECT:创建查询描述符,还需要ExecutorStart调用ExecInitXXX初始化算子。节点是CMD_SELECT类型操作,utilityStmt字段和intoClause字段为空

    3)PORTAL_ONE_RETURNING、PORTAL_ONE_MOD_WITH、PORTAL_UTIL_SELECT创建返回元组的描述符。需要将执行后的结果缓存,然后将缓存结果按照要求返回。其中PORTAL_UTIL_SELECT策略:节点是CMD_UTILITY类型操作,utilityStmt字段保持的是FETCH语句(游标使用)、EXECUTE语句、EXPLAIN语句或者SHOW;PORTAL_ONE_RETURNING:适用于stmts链表中只有一个包含RETURNING子句的原子操作;PORTAL_ONE_MOD_WITH:包含一个SELECT查询,有一个data-modifying CTEs;其他场景使用PORTAL_MULTI_QUERY

    4)查询描述符的创建,包括planstate

    5)最后将Portal状态设置为PORTAL_READY,表示已初始化好,准备执行

    PortalRun执行Portal,根据选择的策略调用相关部件进行执行。执行相关DML查询,对数据进行计算和处理。算子分为两类:行执行算子和向量化执行算子。行执行器执行入口ExecutorRun,向量化执行引擎执行入口是ExecuteVectorizedPlan。向量化算子执行函数命名为“ExecVec+算子名”。

    PortalDrop清理Portal,对Portal相关资源进行释放。各个算子的清理函数命名规则“ExecEnd+算子名”或“ExecEndVec+算子名”

    3、向量化执行引擎的执行

    排序Batchsortstate或者物化BatchStore进行取数据时,比如排序后从排序缓存取数据时,仅当forward为true时才拿数据:

    openGauss的BatchStore和Batchsortstate为什么仅ForwardScanDirection取数据-3

    但是,我们在前文可以看到对于standard_ExecutorRun执行时,对于forward向前或者向后都会进入执行。那么就需要继续分析,哪些场景支持哪些扫描方向。

    3、扫描方向的确定

    pg_plan_queries函数中生成执行计划,可以看到分为两个分支:CMD_UTILITY和pg_pan_query。

    openGauss的BatchStore和Batchsortstate为什么仅ForwardScanDirection取数据-4

    向量化执行计划的转换仅在pg_plan_query函数中进行。CMD_UTILITY分支是不会转换向量化执行计划的。CMD_UTILITY分支比如从游标中获取数据,就分为向前或向后的方向执行;而其他条件,则总是向前扫描的方向。

    向量化执行的方向来自ExecutorRun的入参:

    openGauss的BatchStore和Batchsortstate为什么仅ForwardScanDirection取数据-5

    CMD_UTILITY分支是哪种场景?

    openGauss的BatchStore和Batchsortstate为什么仅ForwardScanDirection取数据-6

    从选择策略上看,仅PORTAL_UTIL_SELECT或者PORTAL_MULTI_QUERY分支。

      PORTAL_MULTI_QUERY:
      PortalRun->PortalRunMulti->ProcessQuery->
      ExecutorRun(queryDesc, ForwardScanDirection, 0L);
      PORTAL_UTIL_SELECT:
      PortalRunUtility->ProcessUtility->standard_ProcessUtility:比如T_FetchStmt
      PerformPortalFetch:cursor的操作
      |-- ....
      |-- |-- PortalRunSelect->ExecutorRun:有扫描方向,向前或向后

      由于没有转换成向量化执行计划,所以走行执行引擎执行。行执行引擎从Tuplestorestate(物化)和Tuplesortstate(排序)取数据时有各个方向的分支处理流程。

      向量化执行引擎执行时,ExecutorRun的方向一定是ForwardScanDirection, 所以BatchStore和Batchsortstate仅实现ForwardScanDirection取数据是正确的!

      相关文章

      Oracle如何使用授予和撤销权限的语法和示例
      Awesome Project: 探索 MatrixOrigin 云原生分布式数据库
      下载丨66页PDF,云和恩墨技术通讯(2024年7月刊)
      社区版oceanbase安装
      Oracle 导出CSV工具-sqluldr2
      ETL数据集成丨快速将MySQL数据迁移至Doris数据库

      发布评论