openGauss核心分析(七):SQL by pass & 經典執行器
執行引擎一般負責查詢的執行,執行引擎在SQL執行棧中起到接收最佳化器生成的執行計劃Plan、並對透過儲存引擎提供的資料讀寫介面,實現對資料進行計算得到查詢的結果集。
在典型的OLTP場景中,簡單查詢佔了很大一部分比例。這種查詢的特徵是隻涉及單表和簡單表示式的查詢,因此為了加速這類查詢,openGauss提出了SQL by pass框架,在parse層對這類查詢做簡單的模式判別後,進入到特殊的執行路徑裡,跳過經典的執行器執行框架,包括運算元的初始化與執行、表示式與投影等經典框架,直接重寫一套簡潔的執行路徑,並且直接呼叫儲存介面,這樣可以大大加速簡單查詢的執行速度。
SQL by pass
enable_opfusion用於控制是否對簡單增刪改查進行最佳化,簡單insert語句在開啟enable_opfusion時的執行計劃如下
由於開啟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列為索引列,後邊可以是常量或者引數。
經典的執行器
關閉enable_opfusion,簡單insert的執行計劃是這樣的
在這種執行流程中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函式負責最後的清理工作,主要是資料結構、快取的清理。
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基本工作流程一致。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/70023856/viewspace-2935367/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- openGauss核心分析(八):執行運算元探究
- openGauss核心:SQL解析過程分析SQL
- openGauss核心分析2:簡單查詢的執行
- openGauss執行器技術
- 多執行緒經典面試題執行緒面試題
- SQL經典練習題48道之七(41-48)SQL
- 解決SQL Server常見的七個經典問題SQLServer
- 深入淺出openGauss的執行器基礎
- ORACLE SQL命令經典OracleSQL
- 經典SQL-1SQL
- 經典SQL-2SQL
- sql執行過程分析SQL
- SQL執行計劃分析SQL
- SQL 執行 - 執行器最佳化SQL
- 教你如何同時執行經典版和Chromium版Edge瀏覽器瀏覽器
- MySQL經典案例分析MySql
- openGauss 對錶執行VACUUM
- openGauss DSS執行緒池執行緒
- openGauss-執行環境
- java 執行緒淺解03[執行緒同步以及經典死鎖]Java執行緒
- Java面試經典題:執行緒池專題Java面試執行緒
- SQL經典五十道題SQL
- 經典SQL面試題1SQL面試題
- 經典SQL面試題2SQL面試題
- 經典SQL語句大全SQL
- 七大快取經典問題快取
- Windows核心執行體物件管理器的操作過程與分析Windows物件
- sql語句執行緩慢分析SQL
- 經典T-SQL程式碼SQL
- SQL經典面試題及答案SQL面試題
- oracle常用經典sql查詢OracleSQL
- sql 查詢經典語句SQL
- 圖靈成立七週年——經典回顧圖靈
- 總結:iOS中多執行緒的經典崩潰iOS執行緒
- win10電腦如何玩經典老遊戲 win10執行經典遊戲的步驟Win10遊戲
- JavaScript同步、非同步、回撥執行順序之經典閉包setTimeout面試題分析JavaScript非同步面試題
- Oracle檢視正在執行的SQL以及執行計劃分析OracleSQL
- 用 Explain 命令分析 MySQL 的 SQL 執行AIMySql