postgresql 格式化查询树为图片 —— pgNodeGraph 与 pg_node2graph

62 篇文章 8 订阅
10 篇文章 1 订阅

一、 PG默认输出格式

1. 相关参数

       postgresql 中提供了一些debug参数,将SQL的查询树和执行计划树打印在错误日志中,并提供了简单的格式化(缩进),但实际上依旧是非常难分析的。一般这个会在学习和分析查询优化器的时候用到,DBA日常工作用的不多。

参数名默认值描述
debug_print_parseoff在错误日志中打印查询树/解析树
debug_print_rewrittenoff在错误日志中打印重写后的查询树/解析树
debug_print_planoff在错误日志中打印执行计划树
debug_pretty_printon输出以上信息时进行简单格式化(缩进)

2. 简单案例

我们看一个例子,查询树的默认输出是什么样的。

  • 开启参数
set debug_print_parse = on;
set debug_print_plan = on;
set debug_pretty_print = on;
  • 执行sql,这里只是非常简单的一个语句
select c2 from t_insert where id=6;
  • 参考错误日志中的查询树
{PLANNEDSTMT 
           :commandType 1 
           :queryId 0 
           :hasReturning false 
           :hasModifyingCTE false 
           :canSetTag true 
           :transientPlan false 
           :dependsOnRole false 
           :parallelModeNeeded false 
           :jitFlags 0 
           :planTree 
              {SEQSCAN 
              :startup_cost 0.00 
              :total_cost 16.12 
              :plan_rows 2 
              :plan_width 44 
              :parallel_aware false 
              :parallel_safe true 
              :async_capable false 
              :plan_node_id 0 
              :targetlist (
                 {TARGETENTRY 
                 :expr 
                    {VAR 
                    :varno 1 
                    :varattno 3 
                    :vartype 1042 
                    :vartypmod 14 
                    :varcollid 100 
                    :varlevelsup 0 
                    :varnosyn 1 
                    :varattnosyn 3 
                    :location 7
                    }
                 :resno 1 
                 :resname c2 
                 :ressortgroupref 0 
                 :resorigtbl 16384 
                 :resorigcol 3 
                 :resjunk false
                 }
              )
              :qual (
                 {OPEXPR 
                 :opno 96 
                 :opfuncid 65 
                 :opresulttype 16 
                 :opretset false 
                 :opcollid 0 
                 :inputcollid 0 
                 :args (
                    {VAR 
                    :varno 1 
                    :varattno 1 
                    :vartype 23 
                    :vartypmod -1 
                    :varcollid 0 
                    :varlevelsup 0 
                    :varnosyn 1 
                    :varattnosyn 1 
                    :location 30
                    }
                    {CONST 
                    :consttype 23 
                    :consttypmod -1 
                    :constcollid 0 
                    :constlen 4 
                    :constbyval true 
                    :constisnull false 
                    :location 33 
                    :constvalue 4 [ 6 0 0 0 0 0 0 0 ]
                    }
                 )
                 :location 32
                 }
              )
              :lefttree <> 
              :righttree <> 
              :initPlan <> 
              :extParam (b)
              :allParam (b)
              :scanrelid 1
              }
           :rtable (
              {RTE 
              :alias <> 
              :eref 
                 {ALIAS 
                 :aliasname t_insert 
                 :colnames ("id" "c1" "c2" "c3")
                 }
              :rtekind 0 
              :relid 16384 
              :relkind r 
              :rellockmode 1 
              :tablesample <> 
              :lateral false 
              :inh false 
              :inFromCl true 
              :requiredPerms 2 
              :checkAsUser 0 
              :selectedCols (b 8 10)
              :insertedCols (b)
              :updatedCols (b)
              :extraUpdatedCols (b)
              :securityQuals <>
              }
           )
           :resultRelations <> 
           :appendRelations <> 
           :subplans <> 
           :rewindPlanIDs (b)
           :rowMarks <> 
           :relationOids (o 16384)
           :invalItems <> 
           :paramExecTypes <> 
           :utilityStmt <> 
           :stmt_location 0 
           :stmt_len 34
           }

已经很复杂,肉眼难以直接分析。

二、 pg_node2graph工具

pg_node2graph工具是在pgNodeGraph的基础上做了些加强,这里我们以它进行测试。

1. 依赖包

yum -y install graphviz
yum -y install gcc-c++

2. 下载安装

  • 下载地址

GitHub - japinli/pg_node2graph

  • 解压文件

其中 pg_node2graph 是执行脚本,nodes目录存放待分析文件,images存放格式化后的图片。 

  •  源码文件node2dot.cc 添加头文件 #include <cstdlib>

github中的文档没有写,但是如果不按以下处理执行时会报错

#include <cassert>
#include <cstdlib>
#include <cstring>
#include <fstream>
#include <getopt.h>
#include <iostream>
#include <map>
#include <queue>
#include <stack>
#include <string>
#include <vector>

3. 保存查询树文本至nodes目录

就是前面非常长的那一串

4. 运行 pg_node2graph 脚本

这里我把对应路径加到了环境变量,所以直接执行就可以

5. images目录查看或下载图片

 图片如下,相对而言清晰很多。

 

三、 主要报错及处理

1. 找不到dot命令

-bash-4.2$ pg_node2graph 
which: no dot in (/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin)

dot是Linux中的一个画图工具,但yum安装的时候不叫dot,应该装

yum -y install graphviz

2. 找不到g++命令

-bash-4.2$ pg_node2graph
/data/postgres/home/postgres/pg_node2graph-main/pg_node2graph: line 29: g++: command not found

解决方法

yum -y install gcc-c++

3. error: ‘exit’ was not declared in this scope

-bash-4.2$ pg_node2graph 
node2dot.cc: In function ‘int main(int, char**)’:
node2dot.cc:91:10: error: ‘exit’ was not declared in this scope
    exit(0);
          ^
node2dot.cc:108:9: error: ‘exit’ was not declared in this scope
   exit(1);
         ^
node2dot.cc:115:9: error: ‘exit’ was not declared in this scope
   exit(1);

解决方法

源码文件node2dot.cc 添加头文件 #include <cstdlib>

参考

https://github.com/japinli/pg_node2graph
https://github.com/shenyuflying/pgNodeGraph
https://blog.csdn.net/ALL_BYA/article/details/121790213
https://blog.csdn.net/weixin_44314171/article/details/107360760
https://blog.csdn.net/m0_38059875/article/details/
 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Hehuyi_In

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值