執(zhí)行引擎一般負責查詢的執(zhí)行,執(zhí)行引擎在SQL執(zhí)行棧中起到接收優(yōu)化器生成的執(zhí)行計劃Plan、并對通過存儲引擎提供的數據讀寫接口,實現對數據進行計算得到查詢的結果集。
在典型的OLTP場景中,簡單查詢占了很大一部分比例。這種查詢的特征是只涉及單表和簡單表達式的查詢,因此為了加速這類查詢,openGauss提出了SQL by pass框架,在parse層對這類查詢做簡單的模式判別后,進入到特殊的執(zhí)行路徑里,跳過經典的執(zhí)行器執(zhí)行框架,包括算子的初始化與執(zhí)行、表達式與投影等經典框架,直接重寫一套簡潔的執(zhí)行路徑,并且直接調用存儲接口,這樣可以大大加速簡單查詢的執(zhí)行速度。
01
SQL by pass
enable_opfusion用于控制是否對簡單增刪改查進行優(yōu)化,簡單insert語句在開啟enable_opfusion時的執(zhí)行計劃如下:
由于開啟SQL BY PASS,從exec_simple_query過來的語句,會判斷可以走SQL BY PASS,否則進入CreatePortal走經典執(zhí)行流程。
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); // 經典執(zhí)行流程…
進入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適應的場景有:
-
只支持單表增刪改查,不支持join、using。
-
只支持行存表,不支持分區(qū)表,表不支持有觸發(fā)器。
-
不支持active sql、QPS等信息統(tǒng)計特性。
-
不支持正在擴容和縮容的表。
-
不支持查詢或者修改系統(tǒng)列。
- 只支持簡單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列為索引列,后邊可以是常量或者參數。
02
經典的執(zhí)行器
關閉enable_opfusion,簡單insert的執(zhí)行計劃是這樣的:

在這種執(zhí)行流程中Portal是執(zhí)行SQL語句的載體,每一條SQL對應唯一的Portal,不同的查詢類型對應的Portal類型也有區(qū)別。
Portal的生命周期管理在exec_simple_query函數中實現,該函數負責Portal創(chuàng)建、執(zhí)行和清理。Portal執(zhí)行的主要執(zhí)行流程包括PortalStart函數、PortalRun函數、PortalDrop函數幾個部分。其中PortalStart函數負責進行Portal結構體初始化工作,包括執(zhí)行算子初始化、內存上下文分配等;PortalRun函數負責真正的執(zhí)行和運算,它是執(zhí)行器的核心;PortalDrop函數負責最后的清理工作,主要是數據結構、緩存的清理。typedef enum PortalStrategy {PORTAL_ONE_SELECT, // SQL語句包含單一的SELECT查詢PORTAL_ONE_RETURNING, // INSERT/UPDATE/DELETE語句包含ReturningPORTAL_ONE_MOD_WITH, // 查詢語句包含WithPORTAL_UTIL_SELECT, // 工具類型查詢語句,如explainPORTAL_MULTI_QUERY // 所有其他類型查詢語句} PortalStrategy;

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;…}
最終執(zhí)行ExecInsertT完成數據插入。
以上分析了簡單insert語句的兩種執(zhí)行流程,對于delete,update,select基本工作流程一致。#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
-
SQL
+關注
關注
1文章
789瀏覽量
46700 -
數據庫
+關注
關注
7文章
4020瀏覽量
68349 -
執(zhí)行器
+關注
關注
5文章
434瀏覽量
20549
原文標題:數據庫內核分析 - SQL by pass & 經典執(zhí)行器
文章出處:【微信號:OSC開源社區(qū),微信公眾號:OSC開源社區(qū)】歡迎添加關注!文章轉載請注明出處。
發(fā)布評論請先 登錄
MOSFET Pass Element Yields 100
華為正式宣布開源數據庫能力,開放openGauss數據庫源代碼
SQL后悔藥,SQL性能優(yōu)化和SQL規(guī)范優(yōu)雅
ADMV8913: X Band, Digitally Tunable, High-Pass and Low-Pass Filter Preliminary Data Sheet
專業(yè)數據庫廠商快立方正式加入openGauss社區(qū)
中軟國際簽署CLA,加入到openGauss社區(qū)
Mybatis的SQL注入審計的基本方法
動態(tài)Sql介紹
openGauss的SQL by pass框架
評論