0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

openGauss的SQL by pass框架

我快闭嘴 来源:Gauss松鼠会 作者:酷哥 2022-09-07 09:44 次阅读

执行引擎一般负责查询的执行,执行引擎在SQL执行栈中起到接收优化器生成的执行计划Plan、并对通过存储引擎提供的数据读写接口,实现对数据进行计算得到查询的结果集。

015eb08c-2dec-11ed-ba43-dac502259ad0.png在典型的OLTP场景中,简单查询占了很大一部分比例。这种查询的特征是只涉及单表和简单表达式的查询,因此为了加速这类查询,openGauss提出了SQL by pass框架,在parse层对这类查询做简单的模式判别后,进入到特殊的执行路径里,跳过经典的执行器执行框架,包括算子的初始化与执行、表达式与投影等经典框架,直接重写一套简洁的执行路径,并且直接调用存储接口,这样可以大大加速简单查询的执行速度。

01

SQL by pass

enable_opfusion用于控制是否对简单增删改查进行优化,简单insert语句在开启enable_opfusion时的执行计划如下:017bcfd2-2dec-11ed-ba43-dac502259ad0.png

由于开启SQL BY PASS,从exec_simple_query过来的语句,会判断可以走SQL BY PASS,否则进入CreatePortal走经典执行流程。

static void exec_simple_query(const char* query_string, MessageType messageType, StringInfo msg = NULL){        /* SQL bypass */        if (runOpfusionCheck) { // 进入SQL by pass            (void)MemoryContextSwitchTo(oldcontext);            void* opFusionObj = OpFusion::FusionFactory(                OpFusion::getFusionType(NULL, NULL, plantree_list), oldcontext, NULL, plantree_list, NULL);            if (opFusionObj != NULL) {                ((OpFusion*)opFusionObj)->setCurrentOpFusionObj((OpFusion*)opFusionObj);                if (OpFusion::process(FUSION_EXECUTE, NULL, completionTag, isTopLevel, NULL)) {                    CommandCounterIncrement();                    finish_xact_command();                    EndCommand(completionTag, dest);                    MemoryContextReset(OptimizerContext);                    break;                }                Assert(0);            }            (void)MemoryContextSwitchTo(t_thrd.mem_cxt.msg_mem_cxt);        }        /*         * Create unnamed portal to run the query or queries in. If there         * already is one, silently drop it.         */        portal = CreatePortal("", true, true); // 经典执行流程

进入InsertFusion::execute完成数据插入操作。

#0  InsertFusion::execute (this=0x7fd93a4104f8, max_rows=9223372036854775807, completionTag=0x7fd933e67020 "@p34663331177")    at opfusion_insert.cpp:297#1  0x0000000001ac00d9 in OpFusion::fusionExecute (this=0x7fd93a4104f8, msg=0x0, completionTag=0x7fd933e67020 "@p34663331177",    isTopLevel=true, isQueryCompleted=0x0) at opfusion.cpp:453#2  0x0000000001ac0389 in OpFusion::process (op=0, msg=0x0, completionTag=0x7fd933e67020 "@p34663331177", isTopLevel=true,    isQueryCompleted=0x0) at opfusion.cpp:491#3  0x000000000193a910 in exec_simple_query (query_string=0x7fd966ad2060 "insert into t1 values(1,200);",    messageType=QUERY_MESSAGE, msg=0x7fd933e67210) at postgres.cpp:2624

SQL by pass适应的场景有:

  • 只支持indexscan和indexonlyscan,且全部WHERE语句的过滤条件都在索引上。

  • 只支持单表增删改查,不支持join、using。

  • 只支持行存表,不支持分区表,表不支持有触发器。

  • 不支持active sql、QPS等信息统计特性。

  • 不支持正在扩容和缩容的表。

  • 不支持查询或者修改系统列。

  • 只支持简单SELECT语句,例如:

SELECT c3 FROM t1 WHERE c1 = ? and c2 =10;

仅可以查询目标表的列,c1和c2列为索引列,后边可以是常量或者参数,可以使用 for update。

  • 只支持简单INSERT语句,例如:

INSERT INTO t1 VALUES (?,10,?);

仅支持一个VALUES,VALUES里面的类型可以是常量和参数,不支持returning。

  • 只支持简单DELETE语句,例如:

DELETE FROM t1 WHERE c1 = ? and c2 = 10;

c1和c2列为索引列,后边可以是常量或者参数。

  • 只支持简单UPDATE语句,例如:

UPDATE t1 SET c3 = c3+? WHERE c1 = ? and c2 = 10;

c3列修改的值可以是常量和参数,也可以是一个简单的表达式,c1c2列为索引列,后边可以是常量或者参数。

02

经典的执行器

关闭enable_opfusion,简单insert的执行计划是这样的:

01a51a18-2dec-11ed-ba43-dac502259ad0.png

在这种执行流程中Portal是执行SQL语句的载体,每一条SQL对应唯一的Portal,不同的查询类型对应的Portal类型也有区别。

typedef enum PortalStrategy {    PORTAL_ONE_SELECT, // SQL语句包含单一的SELECT查询    PORTAL_ONE_RETURNING, // INSERT/UPDATE/DELETE语句包含Returning    PORTAL_ONE_MOD_WITH, // 查询语句包含With    PORTAL_UTIL_SELECT, // 工具类型查询语句,如explain    PORTAL_MULTI_QUERY // 所有其他类型查询语句} PortalStrategy;
Portal的生命周期管理在exec_simple_query函数中实现,该函数负责Portal创建、执行和清理。Portal执行的主要执行流程包括PortalStart函数、PortalRun函数、PortalDrop函数几个部分。其中PortalStart函数负责进行Portal结构体初始化工作,包括执行算子初始化、内存上下文分配等;PortalRun函数负责真正的执行和运算,它是执行器的核心;PortalDrop函数负责最后的清理工作,主要是数据结构、缓存的清理。01d7839a-2dec-11ed-ba43-dac502259ad0.png

PortalRun函数根据查询类型进入不同的处理函数:

bool PortalRun(    Portal portal, long count, bool isTopLevel, DestReceiver* dest, DestReceiver* altdest, char* completionTag){            switch (portal->strategy) {            case PORTAL_ONE_SELECT:            case PORTAL_MULTI_QUERY: // insert从这里进入                PortalRunMulti(portal, isTopLevel, dest, altdest, completionTag);                 /* Prevent portal's commands from being re-executed */                MarkPortalDone(portal);                /* Always complete at end of RunMulti */                result = true;                break;}

最终执行ExecInsertT完成数据插入。

#0  ExecInsertT<false> (state=0x7fdbf1836060, slot=0x7fdbf0c86460, planSlot=0x7fdbf0c86460, estate=0x7fdbf0c74060, canSetTag=true,    options=0, partitionList=0x7fdbf3125860) at nodeModifyTable.cpp:800#1  0x0000000001a684cd in ExecModifyTable (node=0x7fdbf1836060) at nodeModifyTable.cpp:3043#2  0x00000000019f3f93 in ExecModifyTableWrap (node=0x7fdbf1836060) at execProcnode.cpp:785#3  0x00000000019f43b5 in ExecProcNode (node=0x7fdbf1836060) at execProcnode.cpp:1038#4  0x00000000019ed9d5 in ExecutePlan (estate=0x7fdbf0c74060, planstate=0x7fdbf1836060, operation=CMD_INSERT, sendTuples=false,    numberTuples=0, direction=ForwardScanDirection, dest=0x7fdbf13bb9c8, motJitContext=0x0) at execMain.cpp:2163#5  0x00000000019ea25a in standard_ExecutorRun (queryDesc=0x7fdbf1558060, direction=ForwardScanDirection, count=0)    at execMain.cpp:608#6  0x000000000181d6ef in explain_ExecutorRun (queryDesc=0x7fdbf1558060, direction=ForwardScanDirection, count=0)    at auto_explain.cpp:121#7  0x00000000019e9dee in ExecutorRun (queryDesc=0x7fdbf1558060, direction=ForwardScanDirection, count=0) at execMain.cpp:486#8  0x000000000194fed6 in ProcessQuery (plan=0x7fdbf0b7b2e0, sourceText=0x7fdbf13ba060 "insert into t1 values(1,200);", params=0x0,    isMOTTable=false, motJitContext=0x0, dest=0x7fdbf13bb9c8, completionTag=0x7fdbf3126020 "") at pquery.cpp:292#9  0x0000000001953fa1 in PortalRunMulti (portal=0x7fdbf0c7a060, isTopLevel=true, dest=0x7fdbf13bb9c8, altdest=0x7fdbf13bb9c8,    completionTag=0x7fdbf3126020 "") at pquery.cpp:1889#10 0x00000000019525e0 in PortalRun (portal=0x7fdbf0c7a060, count=9223372036854775807, isTopLevel=true, dest=0x7fdbf13bb9c8,    altdest=0x7fdbf13bb9c8, completionTag=0x7fdbf3126020 "") at pquery.cpp:1191#11 0x000000000193ac65 in exec_simple_query (query_string=0x7fdbf13ba060 "insert into t1 values(1,200);",    messageType=QUERY_MESSAGE, msg=0x7fdbf3126210) at postgres.cpp:2720
以上分析了简单insert语句的两种执行流程,对于delete,update,select基本工作流程一致。

审核编辑:汤梓红

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • SQL
    SQL
    +关注

    关注

    1

    文章

    759

    浏览量

    44062
  • 数据库
    +关注

    关注

    7

    文章

    3761

    浏览量

    64268
  • 执行器
    +关注

    关注

    5

    文章

    375

    浏览量

    19319

原文标题:数据库内核分析 - SQL by pass & 经典执行器

文章出处:【微信号:OSC开源社区,微信公众号:OSC开源社区】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    MOSFET Pass Element Yields 100

    In terms of low RON, the best pass transistor for a low-dropout, positive-voltage regulator
    发表于 04-30 09:19 875次阅读
    MOSFET <b class='flag-5'>Pass</b> Element Yields 100

    华为正式宣布开源数据库能力,开放openGauss数据库源代码

    openGauss 是一款开源关系型数据库管理系统,采用木兰宽松许可证 v2 发行。openGauss 内核源自 PostgreSQL,深度融合华为在数据库领域多年的经验,结合企业级场景需求,持续构建竞争力特性。同时 openGauss
    的头像 发表于 07-25 11:11 4644次阅读

    SQL后悔药,SQL性能优化和SQL规范优雅

    每一个好习惯都是一笔财富,本文基于MySQL,分SQL后悔药, SQL性能优化,SQL规范优雅三个方向,分享写SQL的21个好习惯,谢谢阅读,加油哈~ 1. 写完
    的头像 发表于 11-14 09:54 1793次阅读

    ADMV8913: X Band, Digitally Tunable, High-Pass and Low-Pass Filter Preliminary Data Sheet

    ADMV8913: X Band, Digitally Tunable, High-Pass and Low-Pass Filter Preliminary Data Sheet
    发表于 01-27 20:24 9次下载
    ADMV8913: X Band, Digitally Tunable, High-<b class='flag-5'>Pass</b> and Low-<b class='flag-5'>Pass</b> Filter Preliminary Data Sheet

    专业数据库厂商快立方正式加入openGauss社区

    北京快立方科技有限公司(以下简称快立方)签署CLA(Contribution License Agreement, 贡献许可协议),正式加入openGauss社区。     快立方此次携手
    的头像 发表于 04-19 11:23 1935次阅读

    中软国际签署CLA,加入到openGauss社区

    openGauss Housekeeper不仅为openGauss集群实现自动化的高可用主备管理,而且还通过实现浮动IP,为openGauss集群对外呈现统一的浮动IP服务,用户只需要通过统一的浮动IP访问数据库,而无需了解集群
    的头像 发表于 06-30 11:41 2025次阅读
    中软国际签署CLA,加入到<b class='flag-5'>openGauss</b>社区

    openGauss开源社区打造全球领先的开源数据库技术生态

    openGauss Developer Day(openGauss开发者大会)2022在北京顺利召开。这是openGauss开源社区发起并主办的面向数据库开发者的年度活动。
    的头像 发表于 07-21 11:03 1317次阅读

    openGauss 3.1.0版本正式上线!七个方面全面增强

    openGauss 3.1.0 版本是openGauss 2022年发布的Preview版本,版本维护生命周期为0.5年。此次发布包含两个数据库服务端安装包:企业版和轻量版。
    的头像 发表于 10-09 10:04 1173次阅读

    Mybatis的SQL注入审计的基本方法

    SQL注入漏洞作为WEB安全的最常见的漏洞之一,在java中随着预编译与各种ORM框架的使用,注入问题也越来越少。新手代码审计者往往对Java Web应用的多个框架组合而心生畏惧,不知如何下手,希望通过Mybatis
    的头像 发表于 10-17 11:16 1271次阅读

    使用Dockerfile制作openGauss镜像

    获取openGauss企业版3.0.0的安装包和源码文件。这里我用的是CentOS,选择的是企业版。对于只是想体验一下的同学来说选择轻量版就足够了,步骤和主要功能是一样的,优点是包更小,占用存储空间更少,缺点是裁掉了一些功能,具体差别见官方文档。
    的头像 发表于 12-07 15:08 829次阅读

    9SQL4952-9SQL4954-9SQL4958 系列数据表

    9SQL4952-9SQL4954-9SQL4958 系列数据表
    发表于 03-13 20:20 0次下载
    9<b class='flag-5'>SQL4952-9SQL4954-9SQL</b>4958 系列数据表

    动态Sql介绍

    动态Sql介绍 动态 SQL 是 MyBatis 的强大特性之一。如果你使用过 JDBC 或其它类似的框架,你应该能理解根据不同条件拼接 SQL 语句有多痛苦,例如拼接时要确保不能忘记
    的头像 发表于 05-31 09:34 1359次阅读
    动态<b class='flag-5'>Sql</b>介绍

    MyBatis动态sql是什么?MyBatis动态SQL最全教程

    动态 SQL 是 MyBatis 的强大特性之一。在 JDBC 或其它类似的框架中,开发人员通常需要手动拼接 SQL 语句。根据不同的条件拼接 SQL 语句是一件极其痛苦的工作。
    的头像 发表于 08-10 10:18 917次阅读

    中软国际亮相openGauss Developer Day 2024

    2024年6月21日,数据库技术界的年度盛事——openGauss Developer Day 2024在北京昆泰嘉瑞文化中心盛大开幕。这场由openGauss社区主办的大会,吸引了来自全国各地的数据库开发者、技术专家和行业领袖,共同探讨数据库技术的最新趋势和应用实践。
    的头像 发表于 06-22 09:28 626次阅读

    跃昉科技正式加入openGauss社区

    日前,跃昉科技签署CLA(Contribution License Agreement,贡献许可协议),正式加入openGauss社区,致力于推动openGauss RISC-V SIG的发展。
    的头像 发表于 10-18 09:28 353次阅读