热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

openGauss数据库源码解析系列文章——执行器解析(三)

本篇介绍执行器解析中“向量化

在上一篇openGauss数据库源码解析系列文章——执行器解析(二)中,介绍了执行器解析中“7.4 表达式计算”及“7.5 编译执行”的相关内容,本篇将介绍“7.6 向量化引擎”的精彩内容。完整版内容请查看CSDN·Gauss松鼠会专栏博客,以下内容为章节试读:

7.6  向量化引擎

传统的行执行引擎大多采用一次一元组的执行模式,这样在执行过程中CPU大部分时间并没有用来处理数据,更多的是在遍历执行树,就会导致CPU的有效利用率较低。而在面对OLAP场景巨量的函数调用次数,需要巨大的开销。为了解决这一问题,openGauss中增加了向量化引擎。向量化引擎使用了一次一批元组的执行模式,能够大大减少遍历执行节点的开销。一次一批元组的数据运载方式也为某些表达式计算的SIMD(single instruction, multiple data,单指令多数据)化提供了机会,SIMD化能够带来性能上的提升。同时向量化引擎还天然对接列存储,能够较为方便地在底层扫描节点装填向量化的列数据。

向量化引擎的执行算子类似于行执行引擎,包含控制算子、扫描算子、物化算子和连接算子。同样会使用节点表示,继承于行执行节点,执行流程采用递归方式。主要包含的节点有:CStoreScan(顺序扫描),CStoreIndexScan(索引扫描),CStoreIndexHeapScan(利用Bitmap获取元组),VecMaterial(物化),VecSort(排序),VecHashJoin(向量化哈希连接)等,下面将逐一介绍这些执行算子。

7.6.1  控制算子

1. VecResult算子

VecResult算子用于处理只有一个结果返回或WHERE过滤条件为常量的情况,对应的代码源文件是“vecresult.cpp”;对应的主要数据结构是VecResult,VecResult继承于BaseResult。VecResult算子相关的函数包括ExecInitVecResult(初始化节点)、ExecVecResult(执行节点)、ExecReScanVecResult(重置节点)、ExecEndVecResult(退出节点)。

ExecInitVecResult函数用于初始化VecResult执行算子。执行流程如图一所示,主要执行流程如下。

(1) 创建并初始化VecResult执行节点,并为节点创建表达式上下文。
(2) 调用“ExecInitResultTupleSlot(estate, &res_state->ps)”函数分配存储投影结果的slot。
(3) 调用投影表达式初始化函数ExecInitVecExpr依次对ps.targetlist、ps.qual和resconstantqual进行初始化。
(4) 分别调用ExecAssignResultTypeFromTL函数和ExecAssignVectorForExprEval函数进行扫描描述符的初始化和投影结构的创建。

图一  ExecInitVecResult函数执行流程

ExecVecResult函数是执行VecResult的主体函数。执行流程如图二所示,主要执行流程如下。

(1) 检查是否需要计算常量表达式。
(2) 若需要则重新计算表达式,设置检查标识(如果常量计算表达式结果为false时,则设置约束检查标识位)。
(3) 获取结果元组。

图二 ExecVecResult函数执行流程

ExecReScanVecResult函数用于重新执行扫描计划。

ExecEndVecResult函数用于在执行结束时释放执行过程中申请的相关资源(包括存储空间等)。

2. VectorModifyTable算子

VecModifyTable算子用于处理INSERT、UPDATE、DELETE操作,对应的代码源文件是“vecmodifytable.cpp”;对应的主要数据结构是VecModifyTableState,VecModifyTableState继承于ModifyTableState。具体定义代码如下所示:

    typedef struct VecModifyTableState : public ModifyTableState {
    VectorBatch* m_pScanBatch; /* 工作元组 */
    VectorBatch* m_pCurrentBatch; /* 输出元组 */
    } VecModifyTableState;

    VecModifyTable算子相关的函数包括ExecInitVecModifyTable(初始化节点)、ExecVecModifyTable(执行节点)、ExecEndVecModifyTable(退出节点)。

    ExecInitVecModifyTable函数用于初始化VecModifyTable算子,调用ExecInitModifyTable函数实现算子的初始化。

    ExecVecModifyTable函数是执行VecModifyTable算子的主体函数,循环地从子计划中获取目标列并根据要求修改每一列,通过“switch(operation)”处理不同的修改操作,具体的修改操作包括CMD_INSERT(插入)、CMD_DELETE(删除)、CMD_UPDATE(更新)。

    ExecEndVecModifyTable函数用于在执行VecModifyTable算子结束时调用ExecEndModifyTable函数清除相关资源。

    3. VecAppend算子

    VecAppend算子用于处理包含一个或多个子计划的链表,通过遍历子计划链表逐个执行子计划,对应的代码源文件是“vecappend.cpp”;对应的主要数据结构是VecAppendState,VecAppendState继承于AppendState。

    VecAppend算子相关的函数包括ExecInitVecAppend(初始化节点)、ExecVecAppend(执行节点)、ExecReScanAppend(重置节点)、ExecEndVecAppend(退出节点)。

    ExecInitVecAppend函数用于初始化VecAppend算子。执行执行流程如图三所示,主要执行流程如下。

    (1) 创建并初始化执行节点VecAppend。
    (2) 分配存储投影结果的slot。
    (3) 循环初始化子计划链表。
    (4) 初始化扫描描述符并设置初始迭代。

    图三  ExecInitVecAppend函数执行流程

    ExecVecAppend函数是执行VecAppend算子的主体函数。执行流程如图四所示,每次从子计划中获取一条元组,当取回全部元组时,移动到下一个子计划,直到执行全部子计划。

    图四  ExecVecAppend执行流程

    ExecEndVecAppend函数用于在执行结束时清理VecAppend算子,释放相应的子计划。

    7.6.2  扫描算子

    1. CStoreScan算子

    CStoreScan算子用于扫描基础表,按顺序扫描基础表,对应的代码源文件是“veccstore.cpp”;CStoreScan算子对应的主要数据结构是CStoreScanState,CStoreScanState继承于ScanState。具体定义代码如下:

      typedef struct CStoreScanState : ScanState {
      Relation ss_currentDeltaRelation;
      Relation ss_partition_parent;
      TableScanDesc ss_currentDeltaScanDesc;
      bool ss_deltaScan;
      bool ss_deltaScanEnd;
      VectorBatch* m_pScanBatch;
      VectorBatch* m_pCurrentBatch;
      CStoreScanRunTimeKeyInfo* m_pScanRunTimeKeys;
      int m_ScanRunTimeKeysNum;
      bool m_ScanRunTimeKeysReady;
      CStore* m_CStore;
      CStoreScanKey csss_ScanKeys;
      int csss_NumScanKeys;
      bool m_fSimpleMap;
      bool m_fUseColumnRef;
      vecqual_func jitted_vecqual;
      bool m_isReplicaTable; *复制表标记符*/
      } CStoreScanState;

      CStoreScan算子的相关函数包括:ExecInitCStoreScan(初始化节点)、ExecCStoreScan(执行节点)、ExecEndCStoreScan(退出节点)、ExecReScanCStoreScan(重置节点)。

      ExecInitCStoreScan函数用于初始化CStoreScan算子。主要执行流程如下。

      (1) 创建并初始化CStoreScan算子,为节点创建表达式上下文。
      (2) 调用ExecAssignVectorForExprEval函数进行投影表达式的初始化。
      (3) 调用ExecInitResultTupleSlot函数和ExecInitScanTupleSlot函数分别初始化用于投影结果和用于扫描的slot。
      (4) 打开扫描表,调用ExecAssignResultTypeFromTL函数和ExecBuildVecProjectionInfo函数分别初始化结果扫描描述符和创建投影结构。

      ……(本节内容未完)


      完整版内容,请点击“阅读原文”



      推荐阅读
      • JDK源码学习之HashTable(附带面试题)的学习笔记
        本文介绍了JDK源码学习之HashTable(附带面试题)的学习笔记,包括HashTable的定义、数据类型、与HashMap的关系和区别。文章提供了干货,并附带了其他相关主题的学习笔记。 ... [详细]
      • 本文介绍了设计师伊振华受邀参与沈阳市智慧城市运行管理中心项目的整体设计,并以数字赋能和创新驱动高质量发展的理念,建设了集成、智慧、高效的一体化城市综合管理平台,促进了城市的数字化转型。该中心被称为当代城市的智能心脏,为沈阳市的智慧城市建设做出了重要贡献。 ... [详细]
      • 开发笔记:加密&json&StringIO模块&BytesIO模块
        篇首语:本文由编程笔记#小编为大家整理,主要介绍了加密&json&StringIO模块&BytesIO模块相关的知识,希望对你有一定的参考价值。一、加密加密 ... [详细]
      • android listview OnItemClickListener失效原因
        最近在做listview时发现OnItemClickListener失效的问题,经过查找发现是因为button的原因。不仅listitem中存在button会影响OnItemClickListener事件的失效,还会导致单击后listview每个item的背景改变,使得item中的所有有关焦点的事件都失效。本文给出了一个范例来说明这种情况,并提供了解决方法。 ... [详细]
      • 本文讨论了clone的fork与pthread_create创建线程的不同之处。进程是一个指令执行流及其执行环境,其执行环境是一个系统资源的集合。在调用系统调用fork创建一个进程时,子进程只是完全复制父进程的资源,这样得到的子进程独立于父进程,具有良好的并发性。但是二者之间的通讯需要通过专门的通讯机制,另外通过fork创建子进程系统开销很大。因此,在某些情况下,使用clone或pthread_create创建线程可能更加高效。 ... [详细]
      • 本文介绍了深入浅出Linux设备驱动编程的重要性,以及两种加载和删除Linux内核模块的方法。通过一个内核模块的例子,展示了模块的编译和加载过程,并讨论了模块对内核大小的控制。深入理解Linux设备驱动编程对于开发者来说非常重要。 ... [详细]
      • 预备知识可参考我整理的博客Windows编程之线程:https:www.cnblogs.comZhuSenlinp16662075.htmlWindows编程之线程同步:https ... [详细]
      • 先看官方文档TheJavaTutorialshavebeenwrittenforJDK8.Examplesandpracticesdescribedinthispagedontta ... [详细]
      • 如何查询zone下的表的信息
        本文介绍了如何通过TcaplusDB知识库查询zone下的表的信息。包括请求地址、GET请求参数说明、返回参数说明等内容。通过curl方法发起请求,并提供了请求示例。 ... [详细]
      • Java程序设计第4周学习总结及注释应用的开发笔记
        本文由编程笔记#小编为大家整理,主要介绍了201521123087《Java程序设计》第4周学习总结相关的知识,包括注释的应用和使用类的注释与方法的注释进行注释的方法,并在Eclipse中查看。摘要内容大约为150字,提供了一定的参考价值。 ... [详细]
      • 本文讨论了在VMWARE5.1的虚拟服务器Windows Server 2008R2上安装oracle 10g客户端时出现的问题,并提供了解决方法。错误日志显示了异常访问违例,通过分析日志中的问题帧,找到了解决问题的线索。文章详细介绍了解决方法,帮助读者顺利安装oracle 10g客户端。 ... [详细]
      • 在Docker中,将主机目录挂载到容器中作为volume使用时,常常会遇到文件权限问题。这是因为容器内外的UID不同所导致的。本文介绍了解决这个问题的方法,包括使用gosu和suexec工具以及在Dockerfile中配置volume的权限。通过这些方法,可以避免在使用Docker时出现无写权限的情况。 ... [详细]
      • Iamtryingtomakeaclassthatwillreadatextfileofnamesintoanarray,thenreturnthatarra ... [详细]
      • 本文介绍了一个适用于PHP应用快速接入TRX和TRC20数字资产的开发包,该开发包支持使用自有Tron区块链节点的应用场景,也支持基于Tron官方公共API服务的轻量级部署场景。提供的功能包括生成地址、验证地址、查询余额、交易转账、查询最新区块和查询交易信息等。详细信息可参考tron-php的Github地址:https://github.com/Fenguoz/tron-php。 ... [详细]
      • MySQL语句大全:创建、授权、查询、修改等【MySQL】的使用方法详解
        本文详细介绍了MySQL语句的使用方法,包括创建用户、授权、查询、修改等操作。通过连接MySQL数据库,可以使用命令创建用户,并指定该用户在哪个主机上可以登录。同时,还可以设置用户的登录密码。通过本文,您可以全面了解MySQL语句的使用方法。 ... [详细]
      author-avatar
      圈闭仔笨仔
      这个家伙很懒,什么也没留下!
      PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
      Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有