openGauss內核分析:SQL by pass & 經典執行器

来源:https://www.cnblogs.com/huaweiyun/archive/2022/09/08/16668909.html
-Advertisement-
Play Games

摘要:執行引擎一般負責查詢的執行,執行引擎在SQL執行棧中起到接收優化器生成的執行計劃Plan、並對通過存儲引擎提供的數據讀寫介面,實現對數據進行計算得到查詢的結果集。 本文分享自華為雲社區《openGauss內核分析(七):SQL by pass & 經典執行器》,作者:Gauss松鼠會 。 執行 ...


摘要:執行引擎一般負責查詢的執行,執行引擎在SQL執行棧中起到接收優化器生成的執行計劃Plan、並對通過存儲引擎提供的數據讀寫介面,實現對數據進行計算得到查詢的結果集。

本文分享自華為雲社區《openGauss內核分析(七):SQL by pass & 經典執行器》,作者:Gauss松鼠會 。

執行引擎一般負責查詢的執行,執行引擎在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 (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基本工作流程一致。

 

點擊關註,第一時間瞭解華為雲新鮮技術~


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 一般常用寫Bimap保存會報錯GDI+會報錯的寫法 1 public void GetImageLocal() 2 { 3 int num = 9; 4 int initWidth = 256; 5 int initHeight = 256; 6 7 for (var c = '\uff41'; c ...
  • 什麼是 YARP YARP (另一個反向代理) 設計為一個庫,提供核心代理功能,你可以根據應用程式的特定需求進行自定義。 YARP 是使用 .NET的基礎架構構建在 .NET上的。YARP 的主要不同之處在於,它被設計成可以通過 .NET 代碼輕鬆定製和調整,以滿足每個部署場景的特定需求。 同時,Y ...
  • 1.konga核心對象 Kong 的四大核心對象:upstream,target,service,route。下麵分別說: (1)upstream,字面意思上游,實際項目理解是對某一個服務的一個或者多個請求地址的抽象入口,新建upstream可配置基本信息,被動/主動健康檢查。 (2)trarget ...
  • 1.俄羅斯延長接受簡化版認證流程的日期 2022年8月31日,俄羅斯聯邦政府發佈了第1255號法令,主題為“關於第353號法令附錄18的修正”,主要內容是俄羅斯延長接受“簡化版認證流程”的日期,從2022年9月1日延長至2023年9月1日為止。該法令發佈後立即生效。 “簡化版認證流程”的相關細則可以 ...
  • 用戶管理 用戶組 用戶角色 用戶 模板管理 模板組 模板 模板的監控項的參數也可以copy來 加入觸發器 導出模板查看格式 ...
  • 2022-09-08 分組函數 1、按照某個欄位分組並查詢(group by) 以"students"表(id,name,age,gender,is_del,height)為例: select gender from students group by gender; 說明:格式:select 欄位 ...
  • 上一篇文章詳細給大家介紹了標簽的設計與加工,在標簽生命周期流程中,標簽體系設計完成後,便進入標簽加工與上線運行階段,一般來說數據開發團隊會主導此過程,但我們需要關心以下幾個問題: ·標簽如何快速創建和實現標簽邏輯的線上化管理 ·業務人員怎麼參與到標簽建設流程中 ·百萬級別的標簽如何落表 一、加工方式 ...
  • Hello,大家好,我是烤鴨,這幾天消失了一下,主要是線上系統出了點小bug和sql性能問題,在努力搬磚,就把之前的設計模式系列放了一下下,正好趁這個複習鞏固了一下sql執行計劃和sql優化等相關的東西,本篇文章我主要用來學習mysql的執行計劃和索引分類,也和大家分享下吧,也請大神們不吝賜教。 先 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...