转载:PostgreSQL服务过程中的那些事二:Pg服务进程处理简单查询六:执行器执行

前端之家收集整理的这篇文章主要介绍了转载:PostgreSQL服务过程中的那些事二:Pg服务进程处理简单查询六:执行器执行前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

转载来自:

PostgreSQL服务过程中的那些事二:Pg服务进程处理简单查询六:执行器执行

blog.csdn.net/beiigang

beigang.iteye.com


话说查询select cname,comp from test1,test2 where test1.id=test2.id;”发送到服务器端,走查询分支exec_simple_query,先调用start_xact_command初始化了事务管理相关对象和资源,接着调用pg_parse_query,通过Lex和Yacc对传入sql语句进行词法语法解析,生成解析树。下来调用GetTransactionSnapshot方法做内存快照,然后调用pg_analyze_and_rewrite方法,进行语义分析把parsetree转换成querytree,然后对该querytree进行重写。接着调用pg_plan_queries方法,根据querytree做查询规划,生成查询计划树plantree。然后调用了一系列方法CreatePortal、PortalStart、PortalSetResultFormat、CreateDestReceiver、PortalRun、PortalDrop,创建portal、初始化portal、设置结果列格式、创建目的地接收者、运行portal执行查询并返回结果,然后释放portal相关资源,再调用finish_xact_command释放事务相关资源。这个例子终于执行完了。

1

下面是执行plantree的调用序列图。


执行plantree的调用序列图

上图红色方框中显示了执行plantree的过程,主要分为portal创建和初始化(CreatePortal、PortalStart)、执行(PortalRun)、释放资源(PortalDrop)三个部分。portal是个抽象概念,它表示一个正在运行或可运行query的执行状态。Portal支持sql层的CURSOR和协议层的portal。从上图中可以看出,在各个部分,portal调用了执行器executor的对应方法ExecutorStart、ExecutorRun、ExecutorDrop完成了相关操作。

简单描述一下执行过程,方法CreatePortal在内存上下文PortalMemory里创建portal,并在portal管理器"Portal hash"注册(参见《Postgresql服务过程中的那些事一:启动postgres服务进程一.七:初始化portal管理环境》);调用PortalDefineQuery为新建的portal设置sourceText(就是例子里的源sql语句)、stmts(就是上一节讨论的plantree列表)等字段,将portal状态设置为PORTAL_DEFINED;再调用PortalStart初始化portal,在该例子里选择PORTAL_ONE_SELECT策略,调用CreateQueryDesc方法,为portal创建查询描述符,将portal状态设置为PORTAL_READY;调用方法PortalRun,根据选择策略调用相应方法,根据portal相关由plantree转化来的各节点结构由下至上逐层进行处理,涉及扫描数据、进行投射、结果缓存等;最后调用PortalDrop释放portal相关资源。

portal有多个执行策略,依赖于执行什么样的query(其实就是根据不同的sql语句调用不同的方法以完成相应操作)。(注意:在所有情况下,一个portal仅执行一个源sql query,并且从用户的视点,仅产生一个结果。但是,规则重写器可以扩展一个源query成0或多个实际的query。)下面是portal的四种策略

PORTAL_ONE_SELECT:这个portal包含一个SELECT查询。我们增加运行一个执行器作为被要求的结果。这个策略还支持可持有的cursor(为了事务结束后访问结果,执行器结果可以被转储到一个tuplestore里)。

PORTAL_ONE_RETURNING:这个portal包含一个伴有RETURNING子句的INSERT/UPDATE/DELETE查询(由规则重写器重写增加的可能的辅助查询/query)。在第一次执行时,我们运行portal以完成和转储主query的结果到portal的tuplestore里;然后这个结果按要求返回给用户。(我们不支持query的部分遍历悬挂,因为AFTER触发器代码不能处理,并且还因为我们不想在执行所有辅助query时冒失败风险。)

PORTAL_ONE_MOD_WITH:portal包含一个SELECT qiery,但它包含数据修改CTE。这个目前和处理PORTAL_ONE_RETURNING的情况一样,因为需要触发触发器的可能性。将来处理这种情况的行为可以更像PORTAL_ONE_SELECT。

PORTAL_UTIL_SELECT:portal包含一个utility语句,其返回一个象SELECT那样的结果(例如,WXPLAIN或者SHOW)。在第一次执行时,我们运行这个语句任何转储其结果到portal的tuplestore里;然后这个结果按要求的返回给客户端。

PORTAL_MULTI_QUERY:所有其它情况。这儿,我们不支持portal执行:portal的query会被运行以完成第一次调用

下面是portal和其执行状态、策略的类型定义及执行器状态结构定义,其他涉及到节点结构定义略去。

typedefenumPortalStrategy

{

PORTAL_ONE_SELECT,

PORTAL_ONE_RETURNING,

PORTAL_ONE_MOD_WITH,

PORTAL_UTIL_SELECT,

PORTAL_MULTI_QUERY

}PortalStrategy;

typedefenumPortalStatus

{

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;

typedefstructPortalData *Portal;

typedefstructPortalData

{

/* Bookkeeping data */

constchar*name;/* portal's name */

prepStmtName;/* source prepared statement (NULL if none) */

MemoryContextheap;/* subsidiary memory for portal */

ResourceOwnerresowner;/* resources owned by portal */

void(*cleanup) (Portalportal);/* cleanup hook */

SubTransactionIdcreateSubid;/* the ID of the creatingsubxact*/

/*

* if createSubid is InvalidSubTransactionId,the portal is held over from

* a prevIoUs transaction

*/

/* The query or queries the portal will execute */

sourceText;/* text of query (as of 8.4,never NULL) */

commandTag;/* command tag for original query */

List*stmts;/* PlannedStmts and/or utility statements */

CachedPlan*cplan;/* CachedPlan,ifstmtsare from one */

ParamListInfoportalParams;/*paramsto pass to query */

/* Features/options */

PortalStrategystrategy;/* see above */

intcursorOptions;/* DECLARE CURSOR option bits */

/* Status data */

PortalStatusstatus;/* see above */

boolportalPinned;/* a pinned portal can't be dropped */

/* If not NULL,Executor is active; call ExecutorEnd eventually: */

QueryDesc*queryDesc;/* info needed for executor invocation */

/* If portal returns tuples,this is theirtupdesc: */

TupleDesctupDesc;/* descriptor for result tuples */

/* and these are the format codes to use for the columns: */

int16*formats;/* a format code for each column */

* Where we store tuples for a held cursor or a PORTAL_ONE_RETURNING or

* PORTAL_UTIL_SELECT query.(A cursor held past the end of its

* transaction no longer has any active executor state.)

*/

Tuplestorestate*holdStore;/* store forholdablecursors */

holdContext;/* memory containing holdStore */

* atStart,atEnd and portalPos indicate the current cursor position.

* portalPos is zero before the first row,N after fetching N'th row of

* query.After we run off the end,portalPos = # of rows in query,and

* atEnd is true.If portalPos overflows,set posOverflow (this causes us

* to stop relying on its value for navigation).Note that atStart

* implies portalPos == 0,but not the reverse (portalPos could have

* overflowed).

atStart;

atEnd;

posOverflow;

longportalPos;

/* Presentation data,primarily used by the pg_cursors system view */

TimestampTzcreation_time;/* time at which this portal was defined */

visible;/* include this portal in pg_cursors? */

}PortalData;

执行器调用的主工作状态

typedefstructEState

{

NodeTagtype;

/* Basic state for all query types: */

ScanDirectiones_direction;/* current scan direction */

Snapshotes_snapshot;/* timequalto use */

es_crosscheck_snapshot;/*crosschecktimequalfor RI */

es_range_table;/* List of RangeTblEntry */

PlannedStmt*es_plannedstmt;/* link to top of plan tree */

JunkFilter*es_junkFilter;/* top-level junk filter,if any */

/* If query can insert/delete tuples,the command ID to mark them with */

CommandIdes_output_cid;

/* Info about target table(s) for insert/update/delete queries: */

ResultRelInfo*es_result_relations;/* array of ResultRelInfos */

es_num_result_relations;/* length of array */

es_result_relation_info;/* currently active arrayelt*/

/* Stuff used for firing triggers: */

es_trig_target_relations;/* trigger-only ResultRelInfos */

TupleTableSlot*es_trig_tuple_slot;/* for trigger output tuples */

es_trig_oldtup_slot;/* for TriggerEnabled */

/* Parameter info: */

es_param_list_info;/* values of externalparams*/

ParamExecData*es_param_exec_vals;/* values of internalparams*/

/* Other working state: */

es_query_cxt;/* per-query context in which EState lives */

es_tupleTable;/* List of TupleTableSlots */

es_rowMarks;/* List of ExecRowMarks */

uint32es_processed;/* # of tuples processed */

Oides_lastoid;/* lastoidprocessed (by INSERT) */

es_top_eflags;/*eflagspassed to ExecutorStart */

es_instrument;/* OR of InstrumentOption flags */

es_select_into;/* true if doing SELECT INTO */

es_into_oids;/* true to generate OIDs in SELECT INTO */

es_finished;/* true when ExecutorFinish is done */

es_exprcontexts;/* List of ExprContexts within EState */

es_subplanstates;/* List of PlanState for SubPlans */

es_auxmodifytables;/* List of secondary ModifyTableStates */

* this ExprContext is for per-output-tuple operations,such as constraint

* checks and index-value computations.It will be reset for each output

* tuple.Note that it will be created only if needed.

ExprContext*es_per_tuple_exprcontext;

* These fields are for re-evaluating planqualswhen an updated tuple is

* substituted in READ COMMITTED mode.es_epqTuple[] contains tuples that

* scan plan nodes should return instead of whatever they'd normally

* return,or NULL if nothing to return; es_epqTupleSet[] is true if a

* particular array entry is valid; and es_epqScanDone[] is state to

* remember if the tuple has been returned already.Arrays are of size

* list_length(es_range_table) and are indexed by scan nodescanrelid- 1.

HeapTuple*es_epqTuple;/* array of EPQ substitute tuples */

bool*es_epqTupleSet;/* true if EPQ tuple is provided */

es_epqScanDone;/* true if EPQ tuple has been fetched */

* this field added at end ofstructto avoid post-release ABI breakage in

* existing release branches.It'll be in a more logical place in 9.2.

es_trig_newtup_slot;/* for TriggerEnabled */

}EState;

下面是执行这个查询的portal相关内存结构图:


portal相关内存结构图

就到这儿吧。

猜你在找的Postgre SQL相关文章