執(zhí)行引擎一般負(fù)責(zé)查詢的執(zhí)行,執(zhí)行引擎在SQL執(zhí)行棧中起到接收優(yōu)化器生成的執(zhí)行計(jì)劃Plan、并對(duì)通過(guò)存儲(chǔ)引擎提供的數(shù)據(jù)讀寫接口,實(shí)現(xiàn)對(duì)數(shù)據(jù)進(jìn)行計(jì)算得到查詢的結(jié)果集。
![015eb08c-2dec-11ed-ba43-dac502259ad0.png](https://file1.elecfans.com//web2/M00/96/5E/wKgaomTnGTyAU9_zAAAUATprIYk780.png)
01
SQL by pass
enable_opfusion用于控制是否對(duì)簡(jiǎn)單增刪改查進(jìn)行優(yōu)化,簡(jiǎn)單insert語(yǔ)句在開啟enable_opfusion時(shí)的執(zhí)行計(jì)劃如下:![017bcfd2-2dec-11ed-ba43-dac502259ad0.png](https://file1.elecfans.com//web2/M00/96/5E/wKgaomTnGTyACuYWAAB2GUEGJiQ843.png)
由于開啟SQL BY PASS,從exec_simple_query過(guò)來(lái)的語(yǔ)句,會(huì)判斷可以走SQL BY PASS,否則進(jìn)入CreatePortal走經(jīng)典執(zhí)行流程。
static void exec_simple_query(const char* query_string, MessageType messageType, StringInfo msg = NULL)
{
…
/* SQL bypass */
if (runOpfusionCheck) { // 進(jìn)入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); // 經(jīng)典執(zhí)行流程
…
進(jìn)入InsertFusion::execute完成數(shù)據(jù)插入操作。
#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適應(yīng)的場(chǎng)景有:
-
只支持單表增刪改查,不支持join、using。
-
只支持行存表,不支持分區(qū)表,表不支持有觸發(fā)器。
-
不支持active sql、QPS等信息統(tǒng)計(jì)特性。
-
不支持正在擴(kuò)容和縮容的表。
-
不支持查詢或者修改系統(tǒng)列。
- 只支持簡(jiǎn)單SELECT語(yǔ)句,例如:
SELECT c3 FROM t1 WHERE c1 = ? and c2 =10;
僅可以查詢目標(biāo)表的列,c1和c2列為索引列,后邊可以是常量或者參數(shù),可以使用 for update。
-
只支持簡(jiǎn)單INSERT語(yǔ)句,例如:
INSERT INTO t1 VALUES (?,10,?);
僅支持一個(gè)VALUES,VALUES里面的類型可以是常量和參數(shù),不支持returning。
-
只支持簡(jiǎn)單DELETE語(yǔ)句,例如:
DELETE FROM t1 WHERE c1 = ? and c2 = 10;
c1和c2列為索引列,后邊可以是常量或者參數(shù)。
-
只支持簡(jiǎn)單UPDATE語(yǔ)句,例如:
UPDATE t1 SET c3 = c3+? WHERE c1 = ? and c2 = 10;
c3列修改的值可以是常量和參數(shù),也可以是一個(gè)簡(jiǎn)單的表達(dá)式,c1和c2列為索引列,后邊可以是常量或者參數(shù)。
02
經(jīng)典的執(zhí)行器
關(guān)閉enable_opfusion,簡(jiǎn)單insert的執(zhí)行計(jì)劃是這樣的:
![01a51a18-2dec-11ed-ba43-dac502259ad0.png](https://file1.elecfans.com//web2/M00/96/5E/wKgaomTnGTyAbksUAADu7ZiTyyY330.png)
在這種執(zhí)行流程中Portal是執(zhí)行SQL語(yǔ)句的載體,每一條SQL對(duì)應(yīng)唯一的Portal,不同的查詢類型對(duì)應(yīng)的Portal類型也有區(qū)別。
Portal的生命周期管理在exec_simple_query函數(shù)中實(shí)現(xiàn),該函數(shù)負(fù)責(zé)Portal創(chuàng)建、執(zhí)行和清理。Portal執(zhí)行的主要執(zhí)行流程包括PortalStart函數(shù)、PortalRun函數(shù)、PortalDrop函數(shù)幾個(gè)部分。其中PortalStart函數(shù)負(fù)責(zé)進(jìn)行Portal結(jié)構(gòu)體初始化工作,包括執(zhí)行算子初始化、內(nèi)存上下文分配等;PortalRun函數(shù)負(fù)責(zé)真正的執(zhí)行和運(yùn)算,它是執(zhí)行器的核心;PortalDrop函數(shù)負(fù)責(zé)最后的清理工作,主要是數(shù)據(jù)結(jié)構(gòu)、緩存的清理。typedef enum PortalStrategy {
PORTAL_ONE_SELECT, // SQL語(yǔ)句包含單一的SELECT查詢
PORTAL_ONE_RETURNING, // INSERT/UPDATE/DELETE語(yǔ)句包含Returning
PORTAL_ONE_MOD_WITH, // 查詢語(yǔ)句包含With
PORTAL_UTIL_SELECT, // 工具類型查詢語(yǔ)句,如explain
PORTAL_MULTI_QUERY // 所有其他類型查詢語(yǔ)句
} PortalStrategy;
![01d7839a-2dec-11ed-ba43-dac502259ad0.png](https://file1.elecfans.com//web2/M00/96/5E/wKgaomTnGTyADFlrAACIYPmYsRA770.png)
PortalRun函數(shù)根據(jù)查詢類型進(jìn)入不同的處理函數(shù):
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從這里進(jìn)入
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完成數(shù)據(jù)插入。
以上分析了簡(jiǎn)單insert語(yǔ)句的兩種執(zhí)行流程,對(duì)于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
+關(guān)注
關(guān)注
1文章
775瀏覽量
44262 -
數(shù)據(jù)庫(kù)
+關(guān)注
關(guān)注
7文章
3851瀏覽量
64710 -
執(zhí)行器
+關(guān)注
關(guān)注
5文章
378瀏覽量
19430
原文標(biāo)題:數(shù)據(jù)庫(kù)內(nèi)核分析 - SQL by pass & 經(jīng)典執(zhí)行器
文章出處:【微信號(hào):OSC開源社區(qū),微信公眾號(hào):OSC開源社區(qū)】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
MOSFET Pass Element Yields 100
![MOSFET <b class='flag-5'>Pass</b> Element Yields 100](https://file1.elecfans.com//web2/M00/A4/D4/wKgZomUMNd6AZSqMAAAyHawSLpM279.gif)
華為正式宣布開源數(shù)據(jù)庫(kù)能力,開放openGauss數(shù)據(jù)庫(kù)源代碼
SQL后悔藥,SQL性能優(yōu)化和SQL規(guī)范優(yōu)雅
專業(yè)數(shù)據(jù)庫(kù)廠商快立方正式加入openGauss社區(qū)
中軟國(guó)際簽署CLA,加入到openGauss社區(qū)
![中軟國(guó)際簽署CLA,加入到<b class='flag-5'>openGauss</b>社區(qū)](https://file.elecfans.com/web2/M00/04/B7/poYBAGDb6R6AXumUAABWUkJQm5A118.png)
openGauss開源社區(qū)打造全球領(lǐng)先的開源數(shù)據(jù)庫(kù)技術(shù)生態(tài)
openGauss 3.1.0版本正式上線!七個(gè)方面全面增強(qiáng)
Mybatis的SQL注入審計(jì)的基本方法
使用Dockerfile制作openGauss鏡像
9SQL4952-9SQL4954-9SQL4958 系列數(shù)據(jù)表
![9<b class='flag-5'>SQL4952-9SQL4954-9SQL</b>4958 系列數(shù)據(jù)表](https://file.elecfans.com/web1/M00/D9/4E/pIYBAF_1ac2Ac0EEAABDkS1IP1s689.png)
動(dòng)態(tài)Sql介紹
![動(dòng)態(tài)<b class='flag-5'>Sql</b>介紹](https://file1.elecfans.com/web2/M00/88/E5/wKgaomR2pDGACtdxAAAJOf37XAE015.png)
評(píng)論