一、 PG默认输出格式
1. 相关参数
postgresql 中提供了一些debug参数,将SQL的查询树和执行计划树打印在错误日志中,并提供了简单的格式化(缩进),但实际上依旧是非常难分析的。一般这个会在学习和分析查询优化器的时候用到,DBA日常工作用的不多。
参数名 | 默认值 | 描述 |
debug_print_parse | off | 在错误日志中打印查询树/解析树 |
debug_print_rewritten | off | 在错误日志中打印重写后的查询树/解析树 |
debug_print_plan | off | 在错误日志中打印执行计划树 |
debug_pretty_print | on | 输出以上信息时进行简单格式化(缩进) |
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/