偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

數(shù)據(jù)庫(kù)內(nèi)核分析之GPDB and PostgreSQL Portal

開(kāi)發(fā) 前端 其他數(shù)據(jù)庫(kù)
可優(yōu)化語(yǔ)句包括DML,像insert/update/select等語(yǔ)句,這類語(yǔ)句特點(diǎn)是查詢滿足條件的元組返回給用戶或者元組操作后寫入磁盤,之所以稱之為可優(yōu)化語(yǔ)句是因?yàn)檫@類語(yǔ)句通常會(huì)被優(yōu)化器進(jìn)行重寫與優(yōu)化,從而加快查詢速度。

GPDB and PostgreSQL Portal內(nèi)核分析

0.導(dǎo)論

Portal(門戶),也稱為策略選擇模塊,根據(jù)sql語(yǔ)句類型選擇不同的執(zhí)行模塊(ProcessUtility、Executor)。

SQL語(yǔ)句類型包括:可優(yōu)化語(yǔ)句、數(shù)據(jù)定義語(yǔ)句。

可優(yōu)化語(yǔ)句包括DML,像insert/update/select等語(yǔ)句,這類語(yǔ)句特點(diǎn)是查詢滿足條件的元組返回給用戶或者元組操作后寫入磁盤,之所以稱之為可優(yōu)化語(yǔ)句是因?yàn)檫@類語(yǔ)句通常會(huì)被優(yōu)化器進(jìn)行重寫與優(yōu)化,從而加快查詢速度。

數(shù)據(jù)定義語(yǔ)句主要是功能性語(yǔ)句,例如:DDL(Create、Alter、Drop)、DCL(Grant、COMMIT、ROLLBACK)等。

圖片

1.Portal

1.1 入口層

QD執(zhí)行會(huì)從exec_simple_query進(jìn)入,QE執(zhí)行從exec_mpp_query進(jìn)入。

1.2 Portal層

1.2.1 初識(shí)Portal

首先初識(shí)Portal內(nèi)部數(shù)據(jù)結(jié)構(gòu):

圖片

策略只包含一個(gè)SELECT查詢。

select * from t1;

包含一個(gè)INSERT/UPDATE/DELETE查詢,且?guī)ETURNING條件。

INSERT INTO ret_tbl (id) VALUES (3) RETURNING id INTO tableId;

包含一個(gè)SELECT查詢并且有修改的CTE。

WITH ins AS (
INSERT INTO t1 (t1_id) VALUES(1) RETURNING t1_id
)
SELECT * from ins;

例如:下面這個(gè)就不是PORTAL_ONE_MOD_WITH,而是PORTAL_MULTI_QUERY。

WITH ins AS (
SELECT * from t1
) INSERT INTO t2
(t2_id, col2)
SELECT * from ins;

包含一個(gè)utility語(yǔ)句,且該語(yǔ)句執(zhí)行會(huì)返回像SELECT那樣有輸出結(jié)果。

postgres=# explain select * from t1;
QUERY PLAN
-------------------------------------------------------------------------------
Gather Motion 3:1 (slice1; segments: 3) (cost=0.00..431.00 rows=1 width=12)
-> Seq Scan on t1 (cost=0.00..431.00 rows=1 width=12)
Optimizer: Pivotal Optimizer (GPORCA)
(3 rows)

postgres=# EXECUTE t1_fn_ret(2, 'helloworld');
t1_id | col1
-------+------------
2 | helloworld
(1 row)

INSERT 0 1

其他情況,例如:PORTAL_MULTI_QUERY + PORTAL_MULTI_QUERY

PREPARE t1_fn (int, text) AS INSERT INTO t1 VALUES($1, $2);
  • PORTAL_MULTI_QUERY
  • PORTAL_UTIL_SELECT
  • PORTAL_ONE_MOD_WITH
  • PORTAL_ONE_RETURNING
  • PORTAL_ONE_SELECT

狀態(tài)

  • PORTAL_NEW
  • PORTAL_DEFINED
  • PORTAL_READY
  • PORTAL_QUEUE
  • PORTAL_ACTIVE
  • PORTAL_DONE
  • PORTAL_FAILED

這幾個(gè)狀態(tài)會(huì)在下面依次引入。

1.2.2 CreatePortal

創(chuàng)建一個(gè)新的Portal,傳入?yún)?shù)均為: CreatePortal("", true, true),表示創(chuàng)建一個(gè)匿名的Portal,允許重復(fù)且重復(fù)后保持沉默。

CreatePortal邏輯:

Portal
CreatePortal(const char *name, bool allowDup, bool dupSilent)
  • 根據(jù)傳入的第一個(gè)參數(shù)name從哈希表中查找
  • 根據(jù)傳入的第二個(gè)參數(shù)allowDup,如果第一步查找到,從哈希表中決定是否刪除。如果true,則刪除,否則報(bào)錯(cuò)。在哈希表中查找到Portal且允許重復(fù)的情況下,在QD節(jié)點(diǎn)上會(huì)根據(jù)第三個(gè)參數(shù)dupSilent決定是否輸出告警信息。
  • 創(chuàng)建一個(gè)新的Portal,并初始化相應(yīng)參數(shù)。

執(zhí)行完畢后,便創(chuàng)建好了一個(gè)狀態(tài)為PORTAL_NEW的Portal。

1.2.3 PortalDefineQuery

定義portal數(shù)據(jù),包含了:查詢語(yǔ)句sourceText、PlannedStmts、查詢完成標(biāo)記qc。

注意:QD上根據(jù)傳遞進(jìn)來(lái)的stmt來(lái)設(shè)置nodeTag,但是QE上為T_Query,因?yàn)镼E上不是parsed statement,所以不是 T_SelectStmt。

最終設(shè)置Portal狀態(tài)為PORTAL_DEFINED。

1.2.4 PortalStart

準(zhǔn)備好portal,主要有如下幾步:

  • 設(shè)置ddesc,該信息為QD到QE上的額外信息,QD上為NULL,QE上不為NULL。
  • 設(shè)置全局參數(shù),例如:當(dāng)前活躍的portal、resourceOwner、context。
  • 設(shè)置portal參數(shù)字段:portalParams,同樣QD上為NULL,QE上不為NULL。
  • 設(shè)置portal策略(ChoosePortalStrategy)。

如下圖所示:輸入為查詢計(jì)劃鏈表,針對(duì)PORTAL_ONE_SELECT、PORTAL_ONE_MOD_WITH、PORTAL_UTIL_SELECT、PORTAL_ONE_RETURNING都是要求一個(gè)計(jì)劃,首先判斷是Query還是PlannedStmt,一般情況下的查詢語(yǔ)句基本都是PlannedStmt,對(duì)于像PREPARE st(int) as select * from t1之類utility語(yǔ)句第一次調(diào)用ChoosePortalStrategy返回PORTAL_MULTI_QUERY(命中PlannedStmt),第二次調(diào)用返回PORTAL_ONE_SELECT(命中Query)。

圖片

choose

5. 根據(jù)portal策略初始化portal,最重要的是初始化tupDesc與cursor postion。

圖片

例如:"QUERY PLAN"、"t1_id、col1"就是tupDesc。

postgres=# explain select * from t1;
QUERY PLAN
-------------------------------------------------------------------------------
Gather Motion 3:1 (slice1; segments: 3) (cost=0.00..431.00 rows=1 width=12)
-> Seq Scan on t1 (cost=0.00..431.00 rows=1 width=12)
Optimizer: Pivotal Optimizer (GPORCA)
(3 rows)

postgres=# EXECUTE t1_fn_ret(2, 'helloworld');
t1_id | col1
-------+------------
2 | helloworld
(1 row)

INSERT 0 1

不同tupleDesc函數(shù)區(qū)別

  • ExecTypeFromTL

skip resjunk column

  • ExecCleanTypeFromTL

with resjunk column

6. 在執(zhí)行Portal過(guò)程中發(fā)生異常,設(shè)置portal的狀態(tài)為PORTAL_FAILED;否則,下一步。

7. 設(shè)置Portal狀態(tài)為PORTAL_READY。

1.2.5 PortalRun

根據(jù)sql的語(yǔ)句類型選擇不同的執(zhí)行路徑,獲取元組數(shù)據(jù),完成portal工作,運(yùn)行完之后要么Done要么下一輪(READY,而非ACTIVE)。

portal策略執(zhí)行路徑如下:

  • PORTAL_ONE_SELECT

set result = portal->atEnd

  • PORTAL_ONE_RETURNING|PORTAL_ONE_MOD_WITH|PORTAL_UTIL_SELECT

獲取時(shí)數(shù)據(jù)方向包含前進(jìn)/后退

可以從holdStore中獲取,也可以從ExectorRun中獲取

填充holdStore(見(jiàn)下方)

調(diào)用PortalRunSelect返回n行數(shù)據(jù)

設(shè)置狀態(tài)為PORTAL_READY

設(shè)置是否完成運(yùn)行標(biāo)記為portal->atEnd

  • PORTAL_MULTI_QUERY

調(diào)用PortalRunMulti

設(shè)置狀態(tài)為PORTAL_Done

設(shè)置是否完成運(yùn)行標(biāo)記為true

圖片

此外,上述圖中填充holdStore邏輯如下:

  • 調(diào)用PortalCreateHoldStore填充portal->holdStore,通過(guò)工廠函數(shù)CreateDestReceiver構(gòu)造DestReceiver(子類:TStoreState);
  • 根據(jù)portal策略執(zhí)行查詢:PORTAL_ONE_RETURNING、PORTAL_ONE_MOD_WITH 調(diào)用PortalRunMulti,PORTAL_UTIL_SELECT調(diào)用PortalRunUtility。

PortalRunUtility

PortalRunMulti

ProcessQuery

PortalRunUtility

utilityStmt

not utilityStmt

PORTAL_ONE_RETURNING、PORTAL_ONE_MOD_WITH

PORTAL_UTIL_SELECT

圖片

2.游標(biāo)Cursor

2.1 打開(kāi)游標(biāo)

如果不想一次執(zhí)行整個(gè)命令,可以設(shè)置一個(gè)封裝該命令的游標(biāo)(cursor), 然后每次讀取幾行命令結(jié)果。

name [ [ NO ] SCROLL ] CURSOR [ ( arguments ) ] FOR query;

例如:

DECLARE liahona SCROLL CURSOR FOR SELECT * FROM t1;

該命令運(yùn)行機(jī)制為:首先識(shí)別到是一個(gè)數(shù)據(jù)定義語(yǔ)句,便會(huì)調(diào)用ProcessUtility,隨后解析從PlannedStmt中的utilityStmt識(shí)別出是一個(gè)T_DeclareCursorStmt節(jié)點(diǎn),調(diào)用PerformCursorOpen執(zhí)行Declare cursor命令。

PerformCursorOpen處理邏輯如下:

  • query重寫
  • 優(yōu)化器優(yōu)化,生成PlannedStmt
  • 創(chuàng)建Portal(名字為游標(biāo)名),僅調(diào)用PortalStart

2.2 關(guān)閉游標(biāo)

關(guān)閉游標(biāo),實(shí)際就是關(guān)閉Portal,調(diào)用PerformPortalClose。

如下兩個(gè)操作:

CLOSE cursor_name;
CLOSE ALL;

如果傳入的名字為空,則是CLOSE ALL關(guān)閉所有非活躍portal,否則,只關(guān)閉指定的portal(cursor)。

2.3 FETCH or MOVE

FETCH與MOVE語(yǔ)法分別如下:

FETCH [ direction { FROM | IN } ] cursor INTO target;
MOVE [ direction { FROM | IN } ] cursor;

FETCH從游標(biāo)中檢索n行到目標(biāo)中, 目標(biāo)可以是一個(gè)行變量、記錄變量、逗號(hào)分隔的普通變量列表, 就像SELECT INTO一樣, 如果沒(méi)有獲取到數(shù)據(jù),目標(biāo)會(huì)設(shè)為NULL。

MOVE重新定位一個(gè)游標(biāo),而不需要檢索任何數(shù)據(jù),例如:一旦游標(biāo)位置確定,則可以刪除或更新行。

MOVE cursor_variable;
UPDATE table_name
SET column = value, ...
WHERE CURRENT OF cursor_variable;

從實(shí)現(xiàn)層面兩者都會(huì)進(jìn)入到PerformPortalFetch,都被解析為FetchStmt,內(nèi)部有個(gè)成員ismove決定是MOVE還是FETCH。

不管是哪個(gè),都會(huì)指定cursor名,有了這個(gè)名字,便知道了portal,隨后調(diào)用PortalRunFetch來(lái)獲取結(jié)果。

PortalRunFetch內(nèi)部會(huì)像PortalRun運(yùn)行一樣,首先設(shè)置portal狀態(tài)為Active,隨后根據(jù)策略選擇不同的調(diào)用鏈。

  • PORTAL_ONE_SELECT

調(diào)用DoPortalRunFetch

  • PORTAL_ONE_RETURNING|PORTAL_ONE_MOD_WITH|PORTAL_UTIL_SELECT

首先判斷portal內(nèi)部是否有holdStore,如果沒(méi)有會(huì)調(diào)用FillPortalStore,隨后調(diào)用DoPortalRunFetch。

DoPortalRunFetch內(nèi)部實(shí)現(xiàn),會(huì)考慮傳入的direction,決定是前向還是后向等不同方向的掃描,最后調(diào)用PortalRunSelect獲取數(shù)據(jù),注意:gpdb不支持backward scan,但是pg支持。


圖片

責(zé)任編輯:武曉燕 來(lái)源: 光城
相關(guān)推薦

2017-08-24 13:29:19

UDB高可用數(shù)據(jù)庫(kù)

2023-02-10 09:21:31

PG數(shù)據(jù)庫(kù)內(nèi)存

2023-06-28 11:14:18

2024-04-03 09:27:49

后端開(kāi)發(fā)數(shù)據(jù)庫(kù)內(nèi)核

2017-08-25 09:50:42

數(shù)據(jù)庫(kù)MySQL內(nèi)核優(yōu)化

2019-11-19 08:32:26

數(shù)據(jù)庫(kù)HLC事務(wù)

2009-03-23 10:32:47

SQLServer數(shù)據(jù)庫(kù)數(shù)據(jù)類型

2010-05-26 11:10:12

MySQL數(shù)據(jù)庫(kù)

2019-11-20 09:08:46

PostgreSQL數(shù)據(jù)庫(kù)

2022-03-31 16:06:26

PingCAP開(kāi)源

2010-05-27 17:10:03

MySQL數(shù)據(jù)庫(kù)內(nèi)存

2011-02-24 15:04:00

PostgreSQL數(shù)據(jù)庫(kù)psql

2020-07-28 08:54:39

內(nèi)核通信Netlink

2011-03-24 14:40:29

PostgreSQL數(shù)管理

2009-12-24 14:17:27

安全威脅Oracle數(shù)據(jù)庫(kù)

2009-12-30 13:26:48

2010-07-08 09:53:57

SQL Server

2013-09-24 15:19:28

甲骨文Oracle數(shù)據(jù)庫(kù)
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)