openGauss内核分析(七):SQL by pass & 经典执行器 (一)
  lYE0sTgD5uUi 2023年11月02日 63 0

openGauss内核分析(七):SQL by pass & 经典执行器 (一)

酷哥 [openGauss](javascript:void(0);) 2023-01-17 17:55 发表于广东

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

openGauss内核分析(七):SQL by pass & 经典执行器 (一)_执行计划

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

01 SQL by pass

enable_opfusion用于控制是否对简单增删改查进行优化,简单insert语句在开启enable_opfusion时的执行计划如下:

openGauss内核分析(七):SQL by pass & 经典执行器 (一)_执行流程_02

由于开启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 "@p\346\063\331\177")
    at opfusion_insert.cpp:297
#1  0x0000000001ac00d9 in OpFusion::fusionExecute (this=0x7fd93a4104f8, msg=0x0, completionTag=0x7fd933e67020 "@p\346\063\331\177",
    isTopLevel=true, isQueryCompleted=0x0) at opfusion.cpp:453
#2  0x0000000001ac0389 in OpFusion::process (op=0, msg=0x0, completionTag=0x7fd933e67020 "@p\346\063\331\177", 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列修改的值可以是常量和参数,也可以是一个简单的表达式,c1和c2列为索引列,后边可以是常量或者参数。

【版权声明】本文内容来自摩杜云社区用户原创、第三方投稿、转载,内容版权归原作者所有。本网站的目的在于传递更多信息,不拥有版权,亦不承担相应法律责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@moduyun.com

  1. 分享:
最后一次编辑于 2023年11月08日 0

暂无评论

推荐阅读
  X5zJxoD00Cah   2023年11月24日   38   0   0 SQL运算符
  X5zJxoD00Cah   2023年11月22日   40   0   0 逆序SQL
  X5zJxoD00Cah   2023年12月11日   30   0   0 表名SQL
  DF5J4hb0hcmT   2023年12月08日   30   0   0 慢查询druidSQL
lYE0sTgD5uUi