【OpenGauss源码学习 —— (VecToRow)算子】

VecToRow 算子

  • 概述
  • ExecInitVecToRow 函数
    • 功能
    • 参数
    • 步骤
  • ExecVecToRow 函数
    • 功能描述
    • 参数
    • 返回值
    • 执行步骤
    • DevectorizeOneBatch 函数
  • ExecEndVecToRow 函数
  • 总结

声明:本文的部分内容参考了他人的文章。在编写过程中,我们尊重他人的知识产权和学术成果,力求遵循合理使用原则,并在适用的情况下注明引用来源。
本文主要参考了 OpenGauss1.1.0 的开源代码和《OpenGauss数据库源码解析》和《PostgresSQL数据库内核分析》一书

概述

  OpenGaussPortalRun 函数中会实际执行相关的 DML 查询,对数据进行计算和处理。在执行过程中,所有执行算子分为两大类行存储算子向量化算子。这两类算子分别对应行存储执行引擎向量化执行引擎行存储执行引擎的上层入口是 ExecutePlan 函数,向量化执行引擎的上层人口是 ExecuteVectorizedPlan 函数。其中向量化引擎是针对列存储表的执行引擎。如果存在行存储表和列存储表的混合计算,那么行存储执行引擎和向量化执行引擎直接可以通过 VecToRowRowToVec 算子进行相互转换行存储算子执行入口函数的命名规则一般为 “Exec + 算子名” 的形式,向量化算子执行入口函数的命名规则一般为 “ExecVee十算子名” 的形式,通过这样的命名规则,可以快速地找到对应算子的函数入口。
  本文所学习的重点为 VecToRow 算子的执行流程。在 OpenGauss 数据库管理系统中,VecToRow 算子扮演着一个重要的角色,特别是在处理涉及行存储和列存储表的混合计算场景。以下是对 VecToRow 算子的作用和功能的详细概述:

VecToRow 算子的作用:
  VecToRow 算子的主要作用是在行存储执行引擎和向量化执行引擎之间提供数据转换的功能。在具体的操作中,它将向量化格式(主要用于列存储表)的数据转换为行存储格式(适用于行存储表)。这种转换对于数据库系统在处理混合类型的数据(既包括行存储表又包括列存储表)时至关重要。
VecToRow 算子的功能:

  1. 数据格式转换:
  • 将数据从列存储格式转换为行存储格式。
  • 这种转换使得向量化执行引擎处理的数据能够被行存储执行引擎理解和处理。
  1. 支持混合计算:
  • 当查询涉及同时访问行存储表和列存储表时,VecToRow 算子允许这两种数据格式在同一个查询中有效结合。
  • 通过转换,算子确保数据在不同类型的存储和处理引擎之间无缝传递。
  1. 优化查询性能:
  • 在某些情况下,向量化处理(针对列存储)对于特定类型的查询更有效率。然而,对于某些操作,如某些类型的连接或复杂的数据处理,行存储格式可能更为合适。
  • VecToRow 算子使得系统能够在这两种处理方式之间灵活转换,从而优化整体查询性能。
  1. 提高灵活性和兼容性:
  • 此算子提升了数据库系统处理不同数据模型的灵活性。
  • 它确保了即使在混合存储环境下,复杂的查询也能够正确执行,增强了系统的兼容性。

ExecInitVecToRow 函数

  ExecInitVecToRow 函数为 VecToRow 算子的执行准备了必要的状态和上下文环境。

功能

  初始化 VecToRow 算子的执行状态,用于将向量化格式的数据转换为行格式。

参数

  • VecToRow* node: VecToRow 算子节点。
  • EState* estate: 执行状态。
  • int eflags: 执行标志。

步骤

  1. 创建状态结构: 使用 makeNode 函数创建 VecToRowState 结构体。
  2. 初始化状态: 设置计划节点、执行状态和向量化状态。
  3. 结果元组槽初始化: 使用 ExecInitResultTupleSlot 初始化结果元组槽。
  4. 子节点初始化: 使用 ExecInitNode 初始化子节点,屏蔽对特定功能的需求。
  5. 记录列存储分区数: 使用 RecordCstorePartNum 记录列存储的分区数量。
  6. 表达式上下文创建: 为节点创建表达式上下文。
  7. 元组类型初始化: 设置元组类型,不需要初始化投影信息。
  8. 去向量化函数分配: 根据数据类型分配去向量化函数。
  9. 返回状态: 返回初始化完成的 VecToRowState 状态结构。

  函数源码如下所示:(路径:src\gausskernel\runtime\vecexecutor\vecnode\vectortorow.cpp

/** ExecInitVecToRow 函数初始化 VecToRow 算子的执行状态。* 这个函数负责将向量化格式的数据转换为行格式数据。* 参数包括 VecToRow 算子节点、执行状态和执行标志。*/
VecToRowState* ExecInitVecToRow(VecToRow* node, EState* estate, int eflags)
{VecToRowState* state = NULL;// 创建 VecToRowState 结构体state = makeNode(VecToRowState);state->ps.plan = (Plan*)node;     // 指定计划节点state->ps.state = estate;         // 设置执行状态state->ps.vectorized = false;     // 设置为非向量化状态// 初始化结果元组槽// VecToRow 算子不产生自己的元组,只处理子节点的元组。ExecInitResultTupleSlot(estate, &state->ps);// 初始化子节点// 对子节点进行初始化,屏蔽对 REWIND, BACKWARD 或 MARK/RESTORE 的需求。if ((uint32)eflags & EXEC_FLAG_BACKWARD)ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("column store doesn't support backward scan")));outerPlanState(state) = ExecInitNode(outerPlan(node), estate, eflags);RecordCstorePartNum(state, node); // 记录列存储的分区数量// 杂项初始化// 为节点创建表达式上下文ExecAssignExprContext(estate, &state->ps);// 初始化元组类型// 不需要初始化投影信息,因为这个节点不执行投影操作。ExecAssignResultTypeFromTL(&state->ps,ExecGetResultType(outerPlanState(state))->tdTableAmType);state->ps.ps_ProjInfo = NULL;state->m_currentRow = 0;          // 初始化当前行为0state->m_pCurrentBatch = NULL;    // 当前批次指针置为空state->nattrs = ExecGetResultType(&state->ps)->natts; // 设置属性数量state->tts = state->ps.ps_ResultTupleSlot;(void)ExecClearTuple(state->tts);state->tts->tts_nvalid = state->nattrs;state->tts->tts_isempty = false;state->devectorizeFunRuntime = (DevectorizeFun*)palloc0(state->nattrs * sizeof(DevectorizeFun));for (int i = 0; i < state->nattrs; i++) {state->tts->tts_isnull[i] = false;int type_id = state->tts->tts_tupleDescriptor->attrs[i]->atttypid;// 根据类型 ID 分配去向量化函数// 各类型数据有不同的去向量化方法if (COL_IS_ENCODE(type_id)) {switch (type_id) {case BPCHAROID:case TEXTOID:case VARCHAROID:state->devectorizeFunRuntime[i] = DevectorizeOneColumn<VARCHAROID>;break;case TIMETZOID:case TINTERVALOID:case INTERVALOID:case NAMEOID:case MACADDROID:case UUIDOID:state->devectorizeFunRuntime[i] = DevectorizeOneColumn<TIMETZOID>;break;case UNKNOWNOID:case CSTRINGOID:state->devectorizeFunRuntime[i] = DevectorizeOneColumn<UNKNOWNOID>;break;default:state->devectorizeFunRuntime[i] = DevectorizeOneColumn<-2>;break;}} else {if (type_id == TIDOID)state->devectorizeFunRuntime[i] = DevectorizeOneColumn<TIDOID>;elsestate->devectorizeFunRuntime[i] = DevectorizeOneColumn<-1>;}}state->m_ttsvalues = NULL;state->m_ttsisnull = NULL;return state; // 返回初始化好的状态
}

ExecVecToRow 函数

  ExecVecToRow 函数通过以上步骤将向量化数据批次转换为行格式数据,以便在行存储执行引擎中进一步处理。

功能描述

ExecVecToRow 函数负责执行 VecToRow 算子,将向量化批处理数据转换为行格式数据。

参数

  • VecToRowState* state: VecToRow 算子的状态结构体。

返回值

  • 返回 TupleTableSlot*:指向转换后的行格式数据的指针,或在没有更多数据时返回 NULL

执行步骤

  1. 初始化变量

    • 定义并初始化局部变量 PlanState* outer_planTupleTableSlot* tupleVectorBatch* current_batch
    • tuple_subscript 用于在批次中定位特定行。
  2. 处理当前批次

    • state 中获取当前向量化数据批次。
    • 如果当前批次为空,则从子计划节点获取新的批次。
  3. 获取新批次

    • 使用 VectorEngine 函数从子计划节点获取新的向量化数据批次。
    • 如果新批次为空,表示没有更多数据,函数返回 NULL
  4. 更新状态和转换批次

    • 将获取的新批次赋值给 state->m_pCurrentBatch 并重置 state->m_currentRow
    • 调用 DevectorizeOneBatch 函数将新批次的数据从向量化格式转换为行格式。
  5. 检索当前批次的行

    • 使用 state->m_currentRowstate->nattrs 定位当前处理的行。
    • 清空 tuple 并使用状态中的数据填充 tuple
  6. 更新行索引

    • 增加 state->m_currentRow 以处理下一行。
    • 如果已处理完当前批次的所有行,重置批次和行索引。
  7. 存储并返回行数据

    • 调用 ExecStoreVirtualTuple 将处理后的行数据存储到 tuple
    • 返回 tuple

  函数源码如下所示:(路径:src\gausskernel\runtime\vecexecutor\vecnode\vectortorow.cpp

/** ExecVecToRow 函数执行 VecToRow 算子,将向量化批处理数据转换为行格式数据。* 参数 state 是 VecToRowState 结构体,包含算子的当前状态。* 函数返回一个 TupleTableSlot 指针,指向转换后的行格式数据,或在没有更多数据时返回 NULL。*/
TupleTableSlot* ExecVecToRow(VecToRowState* state) /* return: a tuple or NULL */
{PlanState* outer_plan = NULL;TupleTableSlot* tuple = state->tts;VectorBatch* current_batch = NULL;int tuple_subscript;// 获取当前批次的数据current_batch = state->m_pCurrentBatch;if (BatchIsNull(current_batch)) {// 如果当前批次为空,从子计划节点获取新的批次outer_plan = outerPlanState(state);current_batch = VectorEngine(outer_plan);if (BatchIsNull(current_batch))  // 如果没有更多行,则返回 NULLreturn NULL;// 更新状态,记录新的批次和行索引state->m_pCurrentBatch = current_batch;state->m_currentRow = 0;// 将当前批次的数据从向量格式转换为行格式DevectorizeOneBatch(state);}// 从当前批次中检索行tuple_subscript = state->m_currentRow * state->nattrs;(void)ExecClearTuple(tuple);for (int i = 0; i < state->nattrs; i++) {// 从状态中获取转换后的行数据tuple->tts_values[i] = state->m_ttsvalues[tuple_subscript + i];tuple->tts_isnull[i] = state->m_ttsisnull[tuple_subscript + i];}state->m_currentRow++;if (state->m_currentRow >= current_batch->m_rows) {// 如果当前批次的所有行都已处理,标记批次为空current_batch->m_rows = 0;state->m_currentRow = 0;}// 将行数据存储到元组槽中ExecStoreVirtualTuple(tuple);return tuple; // 返回处理后的行数据
}

DevectorizeOneBatch 函数

  DevectorizeOneBatch 主要负责将数据从向量化的存储格式转换为行式格式,这是在将数据从列存储表传递给行存储执行引擎时一个关键的步骤。它通过逐列处理当前批次中的数据,将向量化的列数据转换为标准的行式数据,以便于行存储执行引擎进一步处理。函数源码如下所示:(路径:src\gausskernel\runtime\vecexecutor\vecnode\vectortorow.cpp

/* 将整个批次从向量存储转换为行存储的函数 */
void DevectorizeOneBatch(VecToRowState* state)
{int i;int j;int rows;int cols;VectorBatch* current_batch = NULL;ScalarVector* column = NULL;MemoryContext old_context;current_batch = state->m_pCurrentBatch;rows = current_batch->m_rows; // 当前批次的行数cols = state->nattrs;         // 列数/* 为 m_ttsvalues 分配内存,用于存储列值;* 为 m_ttsisnull 分配内存,用于指示列值是否为 null。* 这两个数组都存放在 VecToRowState 中。 */if (state->m_ttsvalues == NULL) {state->m_ttsvalues = (Datum*)palloc(sizeof(Datum) * cols * BatchMaxSize);state->m_ttsisnull = (bool*)palloc(sizeof(bool) * cols * BatchMaxSize);}/* 循环处理整个批次,逐列进行。 */ExprContext* econtext = state->ps.ps_ExprContext; // 表达式上下文ResetExprContext(econtext); // 重置表达式上下文old_context = MemoryContextSwitchTo(econtext->ecxt_per_tuple_memory);for (i = 0; i < cols; i++) {column = &current_batch->m_arr[i]; // 获取当前列的向量/* 处理常量情况;同时处理 NULL 值情况。 */for (j = 0; j < rows; j++)state->m_ttsisnull[j * cols + i] = IS_NULL(column->m_flag[j]);// 调用去向量化函数处理当前列state->devectorizeFunRuntime[i](state, column, rows, cols, i);}// 恢复原始的内存上下文(void)MemoryContextSwitchTo(old_context);return;
}

ExecEndVecToRow 函数

  ExecEndVecToRow 函数的作用和功能是在执行数据库查询计划时进行清理和资源释放。首先,它清空了与该节点关联的结果元组槽,以确保在下一次使用前不会残留任何旧数据。接下来,它关闭了与该节点关联的子计划,这些子计划是嵌套在主查询中的子查询或连接操作,执行结束后需要关闭以释放资源。这些操作是确保查询执行的正确性和资源管理的重要步骤。ExecEndVecToRow 函数源码如下所示:(路径:src\gausskernel\runtime\vecexecutor\vecnode\vectortorow.cpp

void ExecEndVecToRow(VecToRowState* node)
{// 清空元组表// 这行代码清空了与给定节点关联的结果元组槽。// 结果元组槽通常用于存储查询结果的临时数据结构。(void)ExecClearTuple(node->ps.ps_ResultTupleSlot);// 关闭子计划// 这行代码关闭了与给定节点关联的子计划。// 子计划是查询计划中的嵌套计划,通常是子查询或连接操作。// 执行结束后需要关闭这些子计划以释放资源。ExecEndNode(outerPlanState(node));
}

总结

  VecToRow 算子在 OpenGauss 的架构中起着桥梁的作用,连接了行存储和向量化(列存储)执行引擎。它通过转换数据格式,确保了数据可以在这两种不同的存储和处理模型之间流动,从而支持更复杂和多样化的查询操作。这不仅提高了查询的灵活性和效率,还增强了数据库在处理不同类型数据时的整体性能。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/201340.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

低成本物联网安全芯片ACL16_S 系列,可应用物联网认证、 SIM、防抄板和设备认证等产品上

ACL16_S 芯片是针对物联网认证、 SIM、防抄板和设备认证需求推出的高安全芯片。芯片采用 32 位 ARMCortex™-M0 系列内核&#xff0c;片内集成多种安全密码模块&#xff0c;包括 RSA/ECC DES/TDES、 SHA-1/-256、 AES-128/-192/-256 等国际安全算法&#xff0c;支持真随机数发…

岳阳楼3D模型纹理贴图

在线工具推荐&#xff1a; 3D数字孪生场景编辑器 - GLTF/GLB材质纹理编辑器 - 3D模型在线转换 - Three.js AI自动纹理开发包 - YOLO 虚幻合成数据生成器 - 三维模型预览图生成器 - 3D模型语义搜索引擎 岳阳楼&#xff0c;位于湖南省岳阳市岳阳楼区洞庭北路&#xff0c;地…

Vcenter 6.7 VCSA证书过期问题处理

1. 故障现象 2022年10月25日&#xff0c;登陆VC报错。 按照报错信息&#xff0c;结合官方文档&#xff0c;判断为STS证书过期导致。 vCenter Server Appliance (VCSA) 6.5.x, 6.7.x or vCenter Server 7.0.x 在/var/log/vmware/vpxd-svcs/vpxd-svcs.log看到类似报错: ERRO…

为什么程序员会讨厌PHP编程语言?

闲来无事&#xff0c;逛了某乎看见一篇关于PHP编程的学习指南&#xff0c;深受启发。我们都知道PHP是一种流行的爬虫语言&#xff0c;尤其在Web开发方面。太有很多有点&#xff0c;例如简单易学、支持的成许多等。但是PHP也会存在一些缺点&#xff0c;如代码可读性差&#xff0…

【Java 基础】20 多线程操作方法

文章目录 1.获取和设置线程的名字1&#xff09;获取默认名字2&#xff09;获取自定义的名字 2.判断线程是否启动3.线程的强制执行4.让线程睡一会儿5.中断线程6.守护线程7.线程的礼让 前一节我们介绍了线程的定义、创建方法、状态以及各状态间的转换。在状态转换处只是简单的说明…

Windows下Linkis1.5DSS1.1.2本地调试

1 Linkis: 参考&#xff1a; 单机部署 | Apache Linkis技术分享 | 在本地开发调试Linkis的源码 (qq.com)DataSphere Studio1.0本地调试开发指南 - 掘金 (juejin.cn) 1.1 后端编译 参考【后端编译 | Apache Linkis】】 修改linkis模块下pom.xml,将mysql.connetor.scope修改…

C语言速通笔记(41-62)

40&#xff0e;十六进制转义字符&#xff1a;\x6d才是合法的&#xff0c;前面的0不能写&#xff0c;而且 x 是小写 41&#xff0e;字符型和整型是近亲&#xff1a;两个具有很大的相似之处&#xff0c;所有的字符都有一个它对应的整形数 据的 ASCLL 的数值。如 char a 65 % …

Java Socket编程之基于UDP协议通信

1.说明 Socket&#xff08;套接字&#xff09;是计算机网络编程中用于实现网络通信的一种编程接口或抽象概念。 它提供了一种标准的接口&#xff0c;使应用程序能够通过网络与其他计算机进行通信。 Socket可以看作是应用程序与网络之间的一个通信端点&#xff0c;类似于电话中…

go-fastfds部署心得

我是windows系统安装 Docker Desktop部署 docker run --name go-fastdfs&#xff08;任意的一个名称&#xff09; --privilegedtrue -t -p 3666:8080 -v /data/fasttdfs_data:/data -e GO_FASTDFS_DIR/data sjqzhang/go-fastdfs:lastest docker run&#xff1a;该命令用于运…

揭秘数据库、数据仓库、数据湖和数据湖之家

您是否想知道数据仓库与数据库有何不同&#xff1f;什么是数据湖和数据湖屋 &#xff1f;让我们用一个假设的例子来理解这些。 Bookster.biz 是全球图书销售领域的新热点。业务蓬勃发展&#xff0c;他们需要跟踪大量数据&#xff1a;数百万本书的庞大目录&#xff0c;全球数百…

还记得当初自己为什么选择计算机?一个程序猿的自述与分享

还记得当初自己为什么选择计算机&#xff1f;一个程序猿的自述与分享 大家好&#xff0c;我是微赚淘客系统的小编&#xff0c;也是冬天不穿秋裤&#xff0c;天冷也要风度的程序猿&#xff01;在我年轻的时候&#xff0c;我选择了计算机专业&#xff0c;这条路虽然曲折艰难&…

Matlab 加权均值质心计算(WMN)

文章目录 一、简介二、实现代码三、实现效果参考资料一、简介 思路很简单,即将之前的均值中心,引入相关的权重函数(通常与距离有关),以此为每个点进行赋权,最后即可得到一个加权均值中心: 二、实现代码 %% ********<

07 手写 BA 优化

07 手写 BA 优化 原理见笔记 《后端 1》 世界坐标系 --> 相机坐标系&#xff08;外参&#xff09;–> 归一化坐标 --> 去畸变 --> 像素坐标系&#xff08;内参&#xff09; 由此得到的估计值与实际观测到的像素坐标作差&#xff0c;得到二维误差项。 7.1 误差及…

【五分钟】学会利用cv2.resize()函数实现图像缩放

引言 在numpy知识库&#xff1a;深入理解numpy.resize函数和数组的resize方法中&#xff0c;小编较为详细地探讨了numpy的resize函数背后的机理。从结果来看&#xff0c;numpy.resize函数并不适合对图像进行缩放操作。而opencv中的resize函数虽然和numpy的resize函数同名&…

vue.config.js文件重写打包工具配置信息

重写 Webpack 的配置信息 // cnpm install compression-webpack-plugin6.1.1 -D gzip压缩插件&#xff0c;需要引入 // cnpm i image-webpack-loader8.1.0 --save-dev 图片压缩&#xff0c;不需要引入 // npm i webpack-bundle-analyzer4.7.0 --save-dev …

深入理解pytest测试框架

在软件开发过程中&#xff0c;测试是确保软件质量的关键环节。为了提高测试效率和准确性&#xff0c;Python社区提供了许多优秀的测试框架&#xff0c;其中之一就是pytest。本文将详细介绍pytest的基本概念、特性、使用方法以及在实际项目中的应用。 一、pytest简介 pytest是…

【MATLAB源码-第95期】基于matlab的协作通信中(AF模式)中继选择算法对比。

操作环境&#xff1a; MATLAB 2022a 1、算法描述 1. 最大最小中继选择 (Max-Min Relay Selection)&#xff1a;这种算法选择能够提供最大最小信号强度的中继。它首先计算所有可用中继的信号强度&#xff0c;然后选择那些在最差信道条件下仍能保持最高信号强度的中继。其目的…

Java File类详解(上)

Java File类详解 基础知识 File类是什么&#xff1f; File对象代表路径&#xff0c;路径分为相对路径和绝对路径。 ●File对象就表示一个路径&#xff0c;可以是文件的路径、也可以是文件夹的路径。 ●这个路径可以是存在的&#xff0c;也允许是不存在的。 如路径1:"…

BACnet I/O模块在水利环境监测全自动控制系统中的应用:稳定、高效、实时

前言 “绿水青山就是金山银山”&#xff0c;水利环境一直是国际生态部门关注的重点。随着经济的发展、针对水利环境的监管也日趋严格&#xff0c;尤其是重点河、湖水系、水源地、城市内河等成为重点监管对象&#xff0c;监管力度也愈来愈严格&#xff0c;监测布点密度不断加大。…

IntelliJ IDEA 智能(AI)编码工具插件

文章目录 通义灵码-阿里CodeGeeX-清华大学智谱AIBitoAmazon CodeWhisperer-亚马逊GitHub Copilot - 买不起CodeiumAIXcoder 仅仅自动生成单元测试功能 TestMe插件&#xff08;免费&#xff09;仅仅是模板填充&#xff0c;不智能。 Squaretest插件&#xff08;收费&#xff09;…