PostgreSQL Executor(1): Portal

參考:https://www.cnblogs.com/flying-tiger/p/6100794.html/

Portal的字面意是“入口”吐根。在PostgreSQL中,Portal用來表示一個(gè)正在執(zhí)行的或者是可執(zhí)行的查詢的執(zhí)行狀態(tài)熊户。

Portal記錄了與執(zhí)行相關(guān)的所有信息坑匠,例如查詢樹、計(jì)劃樹和執(zhí)行狀態(tài)雨让。確實(shí)可以將Portal看作執(zhí)行查詢計(jì)劃的“入口”雇盖。

對(duì)于用戶提交的普通查詢語句,在服務(wù)端會(huì)創(chuàng)建一個(gè)匿名的Portal對(duì)象栖忠。而對(duì)于SQL中的游標(biāo)聲明語句崔挖,也會(huì)創(chuàng)建一個(gè)對(duì)應(yīng)的Portal對(duì)象。

Portal的數(shù)據(jù)

執(zhí)行器使用PortalData來存儲(chǔ)查詢計(jì)劃樹庵寞、結(jié)果元組的描述符(TupleDesc)狸相、執(zhí)行狀態(tài)、查詢結(jié)果等數(shù)據(jù)捐川。PortalData結(jié)構(gòu)體定義在src/include/utils/portal.h中脓鹃。

typedef struct PortalData
{
    /* Bookkeeping data */
    const char *name;           /* portal's name */
    ......
    /* The query or queries the portal will execute */
    const char *sourceText;     /* text of query (as of 8.4, never NULL) */
    const char *commandTag;     /* command tag for original query */
    List       *stmts;          /* PlannedStmts and/or utility statements */
    ......
    ParamListInfo portalParams; /* params to pass to query */

    /* Features/options */
    PortalStrategy strategy;    /* see above */

    /* If not NULL, Executor is active; call ExecutorEnd eventually: */
    QueryDesc  *queryDesc;      /* info needed for executor invocation */

    /* If portal returns tuples, this is their tupdesc: */
    TupleDesc   tupDesc;        /* descriptor for result tuples */
    ......
}   PortalData;

Portal的狀態(tài)

Portal有六種狀態(tài),它們的定義如下:

/*
 * A portal is always in one of these states.  It is possible to transit
 * from ACTIVE back to READY if the query is not run to completion;
 * otherwise we never back up in status.
 */
typedef enum PortalStatus
{
    PORTAL_NEW,                  /* freshly created */
    PORTAL_DEFINED,              /* PortalDefineQuery done */
    PORTAL_READY,                /* PortalStart complete, can run it */
    PORTAL_ACTIVE,               /* portal is running (can't delete it) */
    PORTAL_DONE,                 /* portal is finished (don't re-run it) */
    PORTAL_FAILED                /* portal got error (can't re-run it) */
} PortalStatus;

在Portal剛被創(chuàng)建時(shí)古沥,狀態(tài)為PORTAL_NEW瘸右。

通過PortalDefineQuery將查詢計(jì)劃等數(shù)據(jù)設(shè)置到Portal上之后娇跟,Portal的狀態(tài)變?yōu)?code>PORTAL_DEFINED。

通過PortalStart為執(zhí)行做好準(zhǔn)備之后太颤,Portal的狀態(tài)變?yōu)?code>PORTAL_READY逞频。

PortalRun的開始,會(huì)將Portal的狀態(tài)標(biāo)記為PORTAL_ACTIVE栋齿。在PORTAL_MULTI_QUERY的執(zhí)行策略下苗胀,在執(zhí)行完成后會(huì)將Portal的狀態(tài)變更為PORTAL_DONE,而在其它執(zhí)行策略下瓦堵,會(huì)將狀態(tài)變更為PORTAL_READY基协。

而在上述過程中發(fā)生錯(cuò)誤,都會(huì)將Portal的狀態(tài)設(shè)置為PORTAL_FAILED菇用。

可優(yōu)化語句和不可優(yōu)化語句

PostgreSQL將用戶輸入的SQL語句分為兩類:可優(yōu)化語句(Optimizable Statement)和不可優(yōu)化語句(Non-optimizable Statement)澜驮。

可優(yōu)化語句就是通常講的DML語句,包括INSERT/DELETE/UPDATE/SELECT惋鸥。這類語句都要查詢到滿足條件的遠(yuǎn)組并返回給用戶杂穷。在查詢優(yōu)化階段會(huì)根據(jù)查詢優(yōu)化理論進(jìn)行重寫和優(yōu)化以提高查詢效率,因此稱為可優(yōu)化語句卦绣。

不可優(yōu)化語句包括DDL耐量、DCL等語句,例如創(chuàng)建表滤港、刪除表廊蜒、創(chuàng)建用戶等。這類語句包含查詢數(shù)據(jù)之外的各類操作溅漾,功能相對(duì)獨(dú)立山叮,因此也稱為功能性語句。功能性語句沒有優(yōu)化的價(jià)值添履。

Portal的執(zhí)行策略

Portal有五種執(zhí)行策略:

typedef enum PortalStrategy
{
    PORTAL_ONE_SELECT,
    PORTAL_ONE_RETURNING,
    PORTAL_ONE_MOD_WITH,
    PORTAL_UTIL_SELECT,
    PORTAL_MULTI_QUERY
} PortalStrategy;

Portal采用哪種優(yōu)化策略取決于執(zhí)行的是什么樣子的查詢屁倔。需要注意的是,在用戶角度看到的一個(gè)單一的查詢語句經(jīng)過查詢重寫之后可能會(huì)變成零個(gè)或多個(gè)實(shí)際的查詢暮胧。

  • PORTAL_ONE_SELECT

    Portal只包含一個(gè)SELECT查詢锐借。因?yàn)樾枰樵兘Y(jié)果,因此執(zhí)行器被遞增的執(zhí)行叔壤。這個(gè)策略也支持holdable的游標(biāo)(執(zhí)行結(jié)果可以存儲(chǔ)到tuplestore中瞎饲,以便在事務(wù)完成后訪問)口叙。

  • PORTAL_ONE_RETURNING

    Portal包含一個(gè)帶有RETURNING子句(另外也可能有查詢重寫增加的輔助查詢)的INSERT/UPDATE/DELETE查詢炼绘。在第一次執(zhí)行時(shí),Portal被執(zhí)行完成妄田,并將主查詢的結(jié)果存儲(chǔ)到Portal的tuplestore中俺亮,然后將結(jié)果返回給客戶端驮捍。

  • PORTAL_ONE_MOD_WITH

    Portal包含一個(gè)SELECT查詢,同時(shí)存在修改數(shù)據(jù)的CTE(Common Table Expression)脚曾。當(dāng)前處理方式與PORTAL_ONE_RETURNING相同东且。

  • PORTAL_UTIL_SELECT

    Portal包含一個(gè)功能性(Utility)語句,返回類似于SELECT的結(jié)果(比如EXPLAIN和SHOW)本讥。在第一次執(zhí)行時(shí)珊泳,Portal被執(zhí)行完成,并將主查詢的結(jié)果存儲(chǔ)到Portal的tuplestore中拷沸,然后將結(jié)果返回給客戶端色查。

  • PORTAL_MULTI_QUERY

    包含所有其它情況。Portal不支持部分執(zhí)行:在Portal第一次執(zhí)行時(shí)完成所有的查詢撞芍。

具體代碼位于src/backend/tcop/pquery.c中函數(shù)ChoosePortalStrategy秧了。

Portal的執(zhí)行

所有SQL語句的執(zhí)行都必須從一個(gè)Portal開始。Portal的執(zhí)行流程依次經(jīng)歷PortalStart序无、PortalRun验毡、PortalDrop三個(gè)過程。每種執(zhí)行策略都實(shí)現(xiàn)了單獨(dú)的執(zhí)行流程帝嗡,會(huì)經(jīng)歷不同的處理過程晶通。

所有流程都在exec_simple_query函數(shù)內(nèi)部進(jìn)行。Portal的執(zhí)行流程如下:

  1. 調(diào)用函數(shù)CreatePortal創(chuàng)建一個(gè)干凈的Portal哟玷,它的內(nèi)存上下文录择、資源跟蹤器清理函數(shù)都已經(jīng)設(shè)置好,但是sourceText碗降、stmts字段還未設(shè)置隘竭;

  2. 調(diào)用函數(shù)PortalDefineQuery為剛剛創(chuàng)建的Portal設(shè)置sourceText、stmt等讼渊,并且設(shè)置Portal的狀態(tài)為PORTAL_DEFINED动看;

  3. 調(diào)用函數(shù)PortalStart對(duì)定義好的Portal進(jìn)行初始化:

    1. 調(diào)用函數(shù)ChoosePortalStrategy為portal選擇策略;

    2. 如果選擇的是PORTAL_ONE_SELECT爪幻,則調(diào)用CreateQueryDesc為Portal創(chuàng)建查詢描述符菱皆;

    3. 如果選擇的是PORTAL_ONE_RETURNING或者PORTAL_ONE_MOD_WITH,則調(diào)用ExecCleanTypeFromTL為Portal創(chuàng)建返回元組的描述符挨稿;

    4. 對(duì)于PORTAL_UTIL_SELECT則調(diào)用UtilityTupleDescriptor為Portal創(chuàng)建查詢描述符仇轻;

    5. 對(duì)于PORTAL_MULTI_QUERY這里則不做操作;

    6. 將Portal的狀態(tài)設(shè)置為PORTAL_READY奶甘。

  4. 調(diào)用函數(shù)PortalRun執(zhí)行Portal,這就按照既定的策略調(diào)用相關(guān)執(zhí)行部件執(zhí)行Portal篷店;

  5. 調(diào)用函數(shù)PortalDrop清理Portal,釋放資源。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末疲陕,一起剝皮案震驚了整個(gè)濱河市方淤,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌蹄殃,老刑警劉巖携茂,帶你破解...
    沈念sama閱讀 216,591評(píng)論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異诅岩,居然都是意外死亡讳苦,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,448評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門吩谦,熙熙樓的掌柜王于貴愁眉苦臉地迎上來医吊,“玉大人,你說我怎么就攤上這事逮京∏涮茫” “怎么了?”我有些...
    開封第一講書人閱讀 162,823評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵懒棉,是天一觀的道長(zhǎng)草描。 經(jīng)常有香客問我,道長(zhǎng)策严,這世上最難降的妖魔是什么穗慕? 我笑而不...
    開封第一講書人閱讀 58,204評(píng)論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮妻导,結(jié)果婚禮上逛绵,老公的妹妹穿的比我還像新娘。我一直安慰自己倔韭,他們只是感情好术浪,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,228評(píng)論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著寿酌,像睡著了一般胰苏。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上醇疼,一...
    開封第一講書人閱讀 51,190評(píng)論 1 299
  • 那天硕并,我揣著相機(jī)與錄音,去河邊找鬼秧荆。 笑死倔毙,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的乙濒。 我是一名探鬼主播陕赃,決...
    沈念sama閱讀 40,078評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了凯正?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,923評(píng)論 0 274
  • 序言:老撾萬榮一對(duì)情侶失蹤豌蟋,失蹤者是張志新(化名)和其女友劉穎廊散,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體梧疲,經(jīng)...
    沈念sama閱讀 45,334評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡允睹,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,550評(píng)論 2 333
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了幌氮。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片缭受。...
    茶點(diǎn)故事閱讀 39,727評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖该互,靈堂內(nèi)的尸體忽然破棺而出米者,到底是詐尸還是另有隱情,我是刑警寧澤宇智,帶...
    沈念sama閱讀 35,428評(píng)論 5 343
  • 正文 年R本政府宣布蔓搞,位于F島的核電站,受9級(jí)特大地震影響随橘,放射性物質(zhì)發(fā)生泄漏喂分。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,022評(píng)論 3 326
  • 文/蒙蒙 一机蔗、第九天 我趴在偏房一處隱蔽的房頂上張望蒲祈。 院中可真熱鬧,春花似錦萝嘁、人聲如沸梆掸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,672評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽沥潭。三九已至,卻和暖如春嬉挡,著一層夾襖步出監(jiān)牢的瞬間钝鸽,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,826評(píng)論 1 269
  • 我被黑心中介騙來泰國(guó)打工庞钢, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留拔恰,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,734評(píng)論 2 368
  • 正文 我出身青樓基括,卻偏偏與公主長(zhǎng)得像颜懊,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,619評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容