这篇文章主要介绍了PostgreSQL中PlannedStmt结构的日志分析,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。

APPEND->appendplans

APPEND->appendplans是链表结构,有2个元素,每个元素的类型为T_NESTLOOP(内嵌循环),通常的信息与其他节点类型类似,重点是lefttree和righttree均不为空,jointype为0表示INNER_JOIN

LIMIT->SORT->APPEND->appendplans->head
lefttree
进入第一个元素的左树

:lefttree{SEQSCAN/T_SEQSCAN类型的Node,顺序扫描:startup_cost0.00:total_cost12.00:plan_rows1//涉及的行数:plan_width256//平均行宽:parallel_awarefalse:parallel_safetrue:plan_node_id5//Planid:targetlist(...)//省略:qual({OPEXPR:opno98//PG_OPERATOROIDoftheoperator,texteq字符串相等:opfuncid67//PG_PROCOIDofunderlyingfunction,texteq字符串相等:opresulttype16//PG_TYPEOIDofresultvalue,bool值:opretsetfalse:opcollid0//pg_collation:inputcollid100//输入的collation(default):args(//参数,链表类型{RELABELTYPE//第1个参数为RelabelType类型:arg//指向Expr的指针,实际类型为VAR{VAR//第:varno4//在rtable中处于第4个位置的RTE:varattno2//属性编号:vartype1043//类型,pg_typeOID,varchar:vartypmod14:varcollid100:varlevelsup0:varnoold4//原始的varno:varoattno2//原始的varattno:location110//token位置(在SQL语句中)}:resulttype25:resulttypmod-1:resultcollid100:relabelformat2:location-1}{CONST//第2个参数为Const类型:consttype25//pg_typeOID:consttypmod-1//:constcollid100//:constlen-1:constbyvalfalse//传值?如为false,则constvalue中的前4个字节为value的说明,在这个案例中,为32(即2的4次方),从第5个字节开始,长度为4的字符串:constisnullfalse:location205//token所在位置:constvalue8[3200049484849]//即字符串"1001"}):location-1}):lefttree<>//左树为空:righttree<>//右树为空:initPlan<>//无初始化Plan:extParam(b):allParam(b):scanrelid4//扫描第4号RTE}

rigthtree
进入第一个元素的右树

:righttree{HASHJOIN//NestLoop右树节点类型是HashJoin(t_grxxjoint_jfxx):startup_cost16.15:total_cost36.12:plan_rows7//涉及的行数:plan_width180//平均行大小:parallel_awarefalse:parallel_safetrue:plan_node_id6//计划节点id:targetlist(...)//投影列,省略:qual<>//表达式:lefttree//左树,暂时折叠{...}:righttree//右树,暂时折叠{...}:initPlan<>//初始化Plan:extParam(b):allParam(b):jointype0//INNER_JOIN:inner_uniquefalse//非唯一innerjoin:joinqual<>:hashclauses(//hash信息,类型为OpExpr{OPEXPR:opno98//pg_operatorOid,"=",texteq:opfuncid67//pg_procOid,texteq:opresulttype16:opretsetfalse:opcollid0//defaultcollation:inputcollid100:args(//参数链表{RELABELTYPE//第1个元素RelabelType:arg{VAR//VAR类型:varno65001//TODO:varattno1//第1列:vartype1043//字符串,varchar:vartypmod14:varcollid100:varlevelsup0:varnoold7//原varno,7号RTE,即t_jfxx:varoattno1//原属性no:location171//SQL语句中的token位置}:resulttype25:resulttypmod-1:resultcollid100:relabelformat2:location-1}{RELABELTYPE//第1个元素RelabelType:arg{VAR//VAR类型:varno65000:varattno1:vartype1043:vartypmod14:varcollid100:varlevelsup0:varnoold5//5号RTE,即t_grxx:varoattno2//2号属性:location157}:resulttype25:resulttypmod-1:resultcollid100:relabelformat2:location-1}):location-1})}:initPlan<>//无初始化Plan:extParam(b):allParam(b):jointype0//INNER_JOIN:inner_uniquefalse:joinqual<>:nestParams<>

下面考察HashJoin的左树和右树,首先看左树
...head(Plan)->righttree(HashJoin)->lefttree

:lefttree{SEQSCAN//顺序扫描:startup_cost0.00:total_cost17.20:plan_rows720:plan_width84:parallel_awarefalse:parallel_safetrue:plan_node_id7//计划id:targetlist(...):qual<>:lefttree<>:righttree<>:initPlan<>:extParam(b):allParam(b):scanrelid7//编号为7的RTE即t_jfxx}

再看HashJoin右树
...head(Plan)->righttree(HashJoin)->righttree

:righttree{HASH//Hash操作(创建Hash表):startup_cost16.12:total_cost16.12:plan_rows2//涉及2行:plan_width134:parallel_awarefalse:parallel_safetrue:plan_node_id8:targetlist(...):qual<>:lefttree//左树也是一个Plan{SEQSCAN//左树为顺序扫描:startup_cost0.00:total_cost16.12:plan_rows2:plan_width134:parallel_awarefalse:parallel_safetrue:plan_node_id9:targetlist(...):qual({OPEXPR//OpExpr类型:opno98:opfuncid67:opresulttype16:opretsetfalse:opcollid0:inputcollid100:args({RELABELTYPE:arg{VAR:varno5//5号RTE,即t_grxx:varattno1//第1个列,即dwbh:vartype1043:vartypmod14:varcollid100:varlevelsup0:varnoold5:varoattno1:location124}:resulttype25:resulttypmod-1:resultcollid100:relabelformat2:location-1}{CONST:consttype25:consttypmod-1:constcollid100:constlen-1:constbyvalfalse//非参数传递:constisnullfalse:location205:constvalue8[3200049484849]//字符串"1001"}):location-1}):lefttree<>//子左树的左树为空:righttree<>//子左树的右树为空:initPlan<>:extParam(b):allParam(b):scanrelid5//扫描的RTE,5号即t_grxx}:righttree<>//右树为空:initPlan<>:extParam(b):allParam(b):skewTable16397//HashJoin的表Oid:skewColumn1//列序号:skewInheritfalse:rows_total0}

LIMIT->SORT->APPEND->appendplans->head->next

子查询中的第2个NestLoop参照LIMIT->SORT->APPEND->appendplans->head即可,条件变为dwbh="1002",其他与链表中的head元素无异,不再累述三、小结

1、计划树结构:通过日志输出分析计划树结构;
2、重要的数据结构:RTE、Plan等。

四、附录

如何开启跟踪日志?postgresql.conf配置文件设置参数:

log_destination='csvlog'log_directory='pg_log'#与postgresql.conf文件在同一级目录log_filename='postgresql-%Y-%m-%d_%H%M%S.log'log_rotation_age=2dlog_rotation_size=100MB#debug_print_parse=on#打印parse树debug_print_rewritten=on#打印parserewrite树debug_print_plan=on#打印plan树debug_pretty_print=on#以pretty方式显示

感谢你能够认真阅读完这篇文章,希望小编分享的“PostgreSQL中PlannedStmt结构的日志分析”这篇文章对大家有帮助,同时也希望大家多多支持亿速云,关注亿速云行业资讯频道,更多相关知识等着你来学习!