pg查询树的简单解读

pg查询树的简单解读,第1张

概述准备环境:PostgreSQL 9.2 前提准备: debug_print_parse = on                  debug_print_rewritten = on                  debug_print_plan = on                  debug_pretty_print = on 启动条件:-l logfile(为了更好的查看log) 准备环境:Postgresql 9.2 前提准备: deBUG_print_parse = on deBUG_print_rewritten = on deBUG_print_plan = on deBUG_pretty_print = on 启动条件:-l logfile(为了更好的查看log) 表:create table aa(a int,b int); 数据:insert into aa values (0,1),(1,0),1); 执行查询语句: select * from aa where ((4-3)/a>1 and a>0); LOG: parse tree: DETAIL: {query :commandType 1 :querySource 0 :canSetTag true :utilityStmt <> :resultRelation 0 :hasAggs false :hasWindowFuncs false :hasSublinks false :hasdistinctOn false :hasRecursive false :hasModifyingCTE false :hasForUpdate false :cteList <> :rtable ( {RTE :alias <> :eref {AliAS :aliasname aa :colnames ("a" "b") } :rtekind 0 :relID 16384 :relkind r :inh true :inFromCl true :requiredPerms 2 :checkAsUser 0 :selectedCols (b 9 10) :modifIEdCols (b) } ) :jointree {FROMEXPR :fromList ( {RANGETBLREF :rtindex 1 } ) :quals {BOolEXPR :boolop and :args ( //这里重点说一下参数,主要看的是参数。表达式是((4-3)/a>1 and a>0),一共有6个参数 {OPEXPR // *** 作符 :opno 521 // *** 作符oID ">" :opfuncID 147 // 调用的函数oID int4gt :opresulttype 16 // 返回的数据类型oID bool :opretset false :opcollID 0 :inputcollID 0 :args ( {OPEXPR // *** 作符 :opno 528 // *** 作符oID "/" :opfuncID 154 // 调用的函数oID int4div :opresulttype 23 // 返回的数据类型oID int4 :opretset false :opcollID 0 :inputcollID 0 :args ( {OPEXPR // *** 作符 :opno 555 // *** 作符oID "-" :opfuncID 181 // 调用的函数oID int4mi :opresulttype 23 // 返回的数据类型oID int4 :opretset false :opcollID 0 :inputcollID 0 :args ( {CONST //常数 :consttype 23 //常量数据类型oID int4 :consttypmod -1 //常量的typmod(现在不是很明白typmod,只知道是数据的一个属性,常为-1) :constcollID 0 :constlen 4 //常量数据的长度 :constbyval true :constisnull false :location 25 :constvalue 4 [ 4 0 0 0 0 0 0 0 ] //第一个参数:4 } {CONST //常数 :consttype 23 //常量数据类型oID int4 :consttypmod -1 //常量的typmod(现在不是很明白typmod,只知道是数据的一个属性,常为-1) :constcollID 0 :constlen 4 //常量数据的长度 :constbyval true :constisnull false :location 27 :constvalue 4 [ 3 0 0 0 0 0 0 0 ] //第二个参数:3 } ) :location 26 } {VAR //变量,就是涉及列的数据,第三个参数:a :varno 1 :varattno 1 :vartype 23 //变量的数据类型oID int4 :vartypmod -1 //变量的typmod :varcollID 0 :varlevelsup 0 :varnoold 1 :varoattno 1 :location 30 } ) :location 29 } {CONST //常数 :consttype 23 //常量数据类型oID int4 :consttypmod -1 //常量的typmod :constcollID 0 :constlen 4 //常量数据的长度 :constbyval true :constisnull false :location 32 :constvalue 4 [ 1 0 0 0 0 0 0 0 ] //第四个参数:1 } ) :location 31 } {OPEXPR // *** 作符 :opno 521 // *** 作符oID ">" :opfuncID 147 // 调用的函数oID int4gt :opresulttype 16 // 返回的数据类型oID bool :opretset false :opcollID 0 :inputcollID 0 :args ( {VAR //变量,就是涉及列的数据,第五个参数:a :varno 1 :varattno 1 :vartype 23 //变量的数据类型oID int4 :vartypmod -1 //变量的typmod :varcollID 0 :varlevelsup 0 :varnoold 1 :varoattno 1 :location 38 } {CONST //常数 :consttype 23 //常量数据类型oID int4 :consttypmod -1 //常量的typmod :constcollID 0 :constlen 4 //常量数据的长度 :constbyval true :constisnull false :location 40 :constvalue 4 [ 0 0 0 0 0 0 0 0 ] //第六个参数:0 } ) :location 39 } ) :location 34 } } :targetList ( //因为是*,所以需要输出的列是a、b {TARGETENTRY :expr {VAR :varno 1 :varattno 1 :vartype 23 :vartypmod -1 :varcollID 0 :varlevelsup 0 :varnoold 1 :varoattno 1 :location 7 } :resno 1 :resname a :ressortgroupref 0 :resorigtbl 16384 :resorigcol 1 :resjunk false } {TARGETENTRY :expr {VAR :varno 1 :varattno 2 :vartype 23 :vartypmod -1 :varcollID 0 :varlevelsup 0 :varnoold 1 :varoattno 2 :location 7 } :resno 2 :resname b :ressortgroupref 0 :resorigtbl 16384 :resorigcol 2 :resjunk false } ) :returningList <> :groupClause <> :havingQual <> :windowClause <> :distinctClause <> :sortClause <> :limitOffset <> :limitCount <> :rowMarks <> :setoperations <> :constraintDeps <> } STATEMENT: select * from aa where ((4-3)/a>1 and a>0); 下面是执行计划的结构体: /* ---------------- * PlannedStmt node * * The output of the planner is a Plan tree headed by a PlannedStmt node. * PlannedStmt holds the "one time" information needed by the executor. * ---------------- */ typedef struct PlannedStmt { NodeTag type;
CmdType commandType; /* select|insert|update|delete */
uint32 queryID; /* query IDentifIEr (copIEd from query) */
bool hasReturning; /* is it insert|update|delete RETURNING? */
bool hasModifyingCTE; /* has insert|update|delete in WITH? */
bool canSetTag; /* do I set the command result tag? */
bool transIEntPlan; /* redo plan when TransactionXmin changes? */
struct Plan *planTree; /* tree of Plan nodes */
List *rtable; /* List of RangeTblEntry nodes */
/* rtable indexes of target relations for INSERT/UPDATE/DELETE */ List *resultRelations; /* integer List of RT indexes,or NIL */
Node *utilityStmt; /* non-null if this is DECLARE CURSOR */
List *subplans; /* Plan trees for SubPlan Expressions */
Bitmapset *rewindplanIDs; /* indices of subplans that require REWIND */
List *rowMarks; /* a List of PlanRowMark's */
List *relationOIDs; /* OIDs of relations the plan depends on */
List *invalitems; /* other dependencIEs,as PlanInvalitems */
int nParamExec; /* number of ParaM_EXEC Params used */ } PlannedStmt;
rewrite未对节点的顺序进行修改,这里就不做讨论了,下面是执行计划,这对节点的顺序发生了修改。
LOG: plan: DETAIL: {PLANNEDSTMT :commandType 1 :queryID 0 :hasReturning false :hasModifyingCTE false :canSetTag true :transIEntPlan false :planTree {SEQSCAN //执行计划看到的估算值 :startup_cost 0.00 :total_cost 47.45 :plan_rows 238 :plan_wIDth 8 :targetList ( {TARGETENTRY :expr {VAR :varno 1 :varattno 1 :vartype 23 :vartypmod -1 :varcollID 0 :varlevelsup 0 :varnoold 1 :varoattno 1 :location 7 } :resno 1 :resname a :ressortgroupref 0 :resorigtbl 16384 :resorigcol 1 :resjunk false } {TARGETENTRY :expr {VAR :varno 1 :varattno 2 :vartype 23 :vartypmod -1 :varcollID 0 :varlevelsup 0 :varnoold 1 :varoattno 2 :location 7 } :resno 2 :resname b :ressortgroupref 0 :resorigtbl 16384 :resorigcol 2 :resjunk false } ) :qual ( {OPEXPR :opno 521 :opfuncID 147 :opresulttype 16 :opretset false :opcollID 0 :inputcollID 0 :args ( {VAR :varno 1 :varattno 1 :vartype 23 :vartypmod -1 :varcollID 0 :varlevelsup 0 :varnoold 1 :varoattno 1 :location 38 } {CONST :consttype 23 :consttypmod -1 :constcollID 0 :constlen 4 :constbyval true :constisnull false :location 40 :constvalue 4 [ 0 0 0 0 0 0 0 0 ] } ) :location 39 } {OPEXPR :opno 521 :opfuncID 147 :opresulttype 16 :opretset false :opcollID 0 :inputcollID 0 :args ( {OPEXPR :opno 528 :opfuncID 154 :opresulttype 23 :opretset false :opcollID 0 :inputcollID 0 :args ( {CONST :consttype 23 :consttypmod -1 :constcollID 0 :constlen 4 :constbyval true :constisnull false :location -1 :constvalue 4 [ 1 0 0 0 0 0 0 0 ] } {VAR :varno 1 :varattno 1 :vartype 23 :vartypmod -1 :varcollID 0 :varlevelsup 0 :varnoold 1 :varoattno 1 :location 30 } ) :location 29 } {CONST :consttype 23 :consttypmod -1 :constcollID 0 :constlen 4 :constbyval true :constisnull false :location 32 :constvalue 4 [ 1 0 0 0 0 0 0 0 ] } ) :location 31 } ) :lefttree <> :righttree <> :initPlan <> :extParam (b) :allParam (b) :scanrelID 1 } :rtable ( {RTE :alias <> :eref {AliAS :aliasname aa :colnames ("a" "b") } :rtekind 0 :relID 16384 :relkind r :inh false :inFromCl true :requiredPerms 2 :checkAsUser 0 :selectedCols (b 9 10) :modifIEdCols (b) } ) :resultRelations <> :utilityStmt <> :subplans <> :rewindplanIDs (b) :rowMarks <> :relationOIDs (o 16384) :invalitems <> :nParamExec 0 } STATEMENT: select * from aa where ((4-3)/a>1 and a>0);
经过查看,对一个查询做的 *** 作如下(在此以上述的SQL语句为例分析,只是针对where后的语句),这是解析时生成的树的结构(重写为对其进行更改): (4 - 3) / a > 1 and a > 0
location 25 27
location 26 30
location 29 32 38 40
location 31 39
location 34
下面是执行的顺序: a > 0 and (4 - 3) / a > 1
location 25 27
location 26 30
location 38 40 29 32
location 39 31
location 34
首先对这颗树进行介绍(以执行计划的顺序介绍,其中首先是进行了 *** 作符优先级的解析,gram里解析的): 首先,这里的都是二叉树结构的,以深度优先进行遍历的,其中根节点是and(location:34),两个子节点分别是(a>0) 和 (4-3)/a>1 。 其中左子又以">"为根结点,a和0作为子节点,同样的右子是以">"为根结点,(4-3)/a和1为子节点,而(4-3)又是以"-"为根结点,4和3为 子节点。 当执行时,首先进行的是39节点的 *** 作(a>0),而后进行的是26节点的 *** 作(4-3),再进行29节点的 *** 作(26,30节点的"/" *** 作),再进行31节点的 *** 作, 然后在对39,40两个节点进行and *** 作。 总结

以上是内存溢出为你收集整理的pg查询树的简单解读全部内容,希望文章能够帮你解决pg查询树的简单解读所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/sjk/1178116.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-02
下一篇 2022-06-02

发表评论

登录后才能评论

评论列表(0条)

保存