这篇文章主要介绍了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_cost 0.00 :total_cost 12.00 :plan_rows 1 //涉及的行数 :plan_width 256 //平均行宽 :parallel_aware false :parallel_safe true :plan_node_id 5 //Plan id :targetlist (...) //省略 :qual ( {OPEXPR :opno 98 //PG_OPERATOR OID of the operator,texteq字符串相等 :opfuncid 67 //PG_PROC OID of underlying function,texteq字符串相等 :opresulttype 16 //PG_TYPE OID of result value,bool值 :opretset false :opcollid 0 //pg_collation :inputcollid 100 //输入的collation(default) :args (//参数,链表类型 {RELABELTYPE //第1个参数为RelabelType类型 :arg //指向Expr的指针,实际类型为VAR {VAR //第 :varno 4 //在rtable中处于第4个位置的RTE :varattno 2 //属性编号 :vartype 1043 //类型,pg_type OID,varchar :vartypmod 14 :varcollid 100 :varlevelsup 0 :varnoold 4 //原始的varno :varoattno 2 //原始的varattno :location 110//token位置(在SQL语句中) } :resulttype 25 :resulttypmod -1 :resultcollid 100 :relabelformat 2 :location -1 } {CONST //第2个参数为Const类型 :consttype 25 //pg_type OID :consttypmod -1 // :constcollid 100 // :constlen -1 :constbyval false //传值?如为false,则constvalue中的前4个字节为value的说明,在这个案例中,为32(即2的4次方),从第5个字节开始,长度为4的字符串 :constisnull false :location 205 //token所在位置 :constvalue 8 [ 32 0 0 0 49 48 48 49 ]//即字符串"1001" } ) :location -1 } ) :lefttree <> //左树为空 :righttree <> //右树为空 :initPlan <> //无初始化Plan :extParam (b) :allParam (b) :scanrelid 4 //扫描第4号RTE }
rigthtree
进入第一个元素的右树
:righttree {HASHJOIN //NestLoop右树节点类型是HashJoin(t_grxx join t_jfxx) :startup_cost 16.15 :total_cost 36.12 :plan_rows 7 //涉及的行数 :plan_width 180 //平均行大小 :parallel_aware false :parallel_safe true :plan_node_id 6 //计划节点id :targetlist (...) //投影列,省略 :qual <> //表达式 :lefttree //左树,暂时折叠 {...} :righttree //右树,暂时折叠 {...} :initPlan <> //初始化Plan :extParam (b) :allParam (b) :jointype 0 //INNER_JOIN :inner_unique false //非唯一inner join :joinqual <> :hashclauses (//hash信息,类型为OpExpr {OPEXPR :opno 98 //pg_operator Oid,"=",texteq :opfuncid 67 //pg_proc Oid,texteq :opresulttype 16 :opretset false :opcollid 0 //default collation :inputcollid 100 :args (//参数链表 {RELABELTYPE//第1个元素 RelabelType :arg {VAR //VAR类型 :varno 65001 //TODO :varattno 1 //第1列 :vartype 1043 //字符串,varchar :vartypmod 14 :varcollid 100 :varlevelsup 0 :varnoold 7 //原varno,7号RTE,即t_jfxx :varoattno 1 //原属性no :location 171//SQL语句中的token位置 } :resulttype 25 :resulttypmod -1 :resultcollid 100 :relabelformat 2 :location -1 } {RELABELTYPE //第1个元素 RelabelType :arg {VAR //VAR类型 :varno 65000 :varattno 1 :vartype 1043 :vartypmod 14 :varcollid 100 :varlevelsup 0 :varnoold 5 //5号RTE,即t_grxx :varoattno 2 //2号属性 :location 157 } :resulttype 25 :resulttypmod -1 :resultcollid 100 :relabelformat 2 :location -1 } ) :location -1 } ) } :initPlan <> //无初始化Plan :extParam (b) :allParam (b) :jointype 0 //INNER_JOIN :inner_unique false :joinqual <> :nestParams <>
下面考察HashJoin的左树和右树,首先看左树
…head(Plan)->righttree(HashJoin)->lefttree
:lefttree {SEQSCAN //顺序扫描 :startup_cost 0.00 :total_cost 17.20 :plan_rows 720 :plan_width 84 :parallel_aware false :parallel_safe true :plan_node_id 7 //计划id :targetlist (...) :qual <> :lefttree <> :righttree <> :initPlan <> :extParam (b) :allParam (b) :scanrelid 7//编号为7的RTE即t_jfxx }
再看HashJoin右树
…head(Plan)->righttree(HashJoin)->righttree
:righttree {HASH //Hash操作(创建Hash表) :startup_cost 16.12 :total_cost 16.12 :plan_rows 2 //涉及2行 :plan_width 134 :parallel_aware false :parallel_safe true :plan_node_id 8 :targetlist (...) :qual <> :lefttree //左树也是一个Plan {SEQSCAN //左树为顺序扫描 :startup_cost 0.00 :total_cost 16.12 :plan_rows 2 :plan_width 134 :parallel_aware false :parallel_safe true :plan_node_id 9 :targetlist (...) :qual ( {OPEXPR //OpExpr类型 :opno 98 :opfuncid 67 :opresulttype 16 :opretset false :opcollid 0 :inputcollid 100 :args ( {RELABELTYPE :arg {VAR :varno 5 //5号RTE,即t_grxx :varattno 1 //第1个列,即dwbh :vartype 1043 :vartypmod 14 :varcollid 100 :varlevelsup 0 :varnoold 5 :varoattno 1 :location 124 } :resulttype 25 :resulttypmod -1 :resultcollid 100 :relabelformat 2 :location -1 } {CONST :consttype 25 :consttypmod -1 :constcollid 100 :constlen -1 :constbyval false //非参数传递 :constisnull false :location 205 :constvalue 8 [ 32 0 0 0 49 48 48 49 ]//字符串"1001" } ) :location -1 } ) :lefttree <> //子左树的左树为空 :righttree <> //子左树的右树为空 :initPlan <> :extParam (b) :allParam (b) :scanrelid 5//扫描的RTE,5号即t_grxx } :righttree <> //右树为空 :initPlan <> :extParam (b) :allParam (b) :skewTable 16397 //HashJoin的表Oid :skewColumn 1 //列序号 :skewInherit false :rows_total 0 }
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 = 2d log_rotation_size = 100MB # debug_print_parse = on #打印parse树 debug_print_rewritten = on #打印parse rewrite树 debug_print_plan = on #打印plan树 debug_pretty_print = on #以pretty方式显示
感谢你能够认真阅读完这篇文章,希望小编分享的“PostgreSQL中PlannedStmt结构的日志分析”这篇文章对大家有帮助,同时也希望大家多多支持亿速云,关注亿速云行业资讯频道,更多相关知识等着你来学习!
原创文章,作者:ItWorker,如若转载,请注明出处:https://blog.ytso.com/205134.html