PostgreSQL 函数调试、诊断、优化 auto_explain

PostgreSQL 函数调试 & auto_explain

作者

digoal

日期

2016-11-21

标签

PostgreSQL , pldebugger , 函数调试 , auto_explain


背景

PostgreSQL的服务端编程能力比较强,不仅支持像java, R, python这种流行的编程语言,另外还内置了一个与Oracle plsql功能几乎一致的plpgsql语言。

对于开发人员来说,有了语言还不够的,调试是非常常见的需求。

所以PostgreSQL的函数语言怎么调试呢,使用pldebugger即可。

pldebugger的安装

https://git.postgresql.org/gitweb/?p=pldebugger.git;a=summary

plpgsql调试方法

https://www.pgadmin.org/docs/1.22/debugger.html

除了函数的调试,还有函数内SQL的执行计划如何观测。

auto_explain

auto_explain 一个比较给力的模块.

用于向日志输出超出定义阈值执行时间的SQL的执行计划。更强大的是可以选择是否输出内嵌SQL的执行计划(如函数中的SQL).

auto_explain的输出更详细的解释可以参考EXPLAIN的解释。或者man EXPLAIN.

SYNOPSIS  EXPLAIN [ ( option [, ...] ) ] statement  EXPLAIN [ ANALYZE ] [ VERBOSE ] statement  where option can be one of:  ANALYZE [ boolean ]  VERBOSE [ boolean ]  COSTS [ boolean ]  BUFFERS [ boolean ]  FORMAT { TEXT | XML | JSON | YAML }  

开启方式有两种 :

1. 通过配置文件postgresql.conf

需要重启数据库。

2. 通过LOAD 'auto_explain';

这个只在当前SESSION生效,不需要重启数据库, 需要超级用户权限。

其实还可以设置local_preload_libraries,session_preload_libraries参数来启用。

例子

1. 修改配置文件:

shared_preload_libraries = 'auto_explain'  

新增如下配置:

auto_explain.log_min_duration = 0  # 为了方便查看,这里把时间设置为0,所有SQL都会被auto_explain捕获输出.实际使用的时候适当调大。如 100ms  
auto_explain.log_analyze = true  # 以下可选  
auto_explain.log_verbose = true  
auto_explain.log_buffers = true  
auto_explain.log_nested_statements = true  

然后重启数据库.重启时会输出一个LOG

postgres@db5-> LOG:  loaded library "$libdir/auto_explain.so"  

下面来执行几条SQL

postgres@db5-> psql -h 127.0.0.1 digoal digoal  
psql (9.1beta1)  
Type "help" for help.  digoal=> select * from tbl_user_info limit 2;  id | firstname | lastname |   corp     
----+-----------+----------+----------  1 | zhou1     | digoal1  | sky-mobi  2 | zhou2     | digoal2  | sky-mobi  
(2 rows)  digoal=> select count(*) from tbl_test;  count    
---------  1000100  
(1 row)  

日志输出

2011-06-08 15:19:14.390 CST,"digoal","digoal",13789,"127.0.0.1:59549",4def2270.35dd,1,"SELECT",2011-06-08 15:19:12 CST,2/18,0,LOG,00  
000,"duration: 0.040 ms  plan:  
Query Text: select * from tbl_user_info limit 2;  
Limit  (cost=0.00..0.04 rows=2 width=31) (actual time=0.020..0.023 rows=2 loops=1)  Output: id, firstname, lastname, corp  Buffers: shared hit=1  ->  Seq Scan on public.tbl_user_info  (cost=0.00..183.00 rows=10000 width=31) (actual time=0.014..0.015 rows=2 loops=1)  Output: id, firstname, lastname, corp  Buffers: shared hit=1",,,,,,,,,"psql"  
2011-06-08 15:19:17.902 CST,"digoal","digoal",13789,"127.0.0.1:59549",4def2270.35dd,2,"SELECT",2011-06-08 15:19:12 CST,2/19,0,LOG,00  
000,"duration: 1232.064 ms  plan:  
Query Text: select count(*) from tbl_test;  
Aggregate  (cost=16927.25..16927.26 rows=1 width=0) (actual time=1232.044..1232.045 rows=1 loops=1)  Output: count(*)  Buffers: shared hit=4426  ->  Seq Scan on public.tbl_test  (cost=0.00..14427.00 rows=1000100 width=0) (actual time=0.015..626.872 rows=1000100 loops=1)  Output: id  Buffers: shared hit=4426",,,,,,,,,"psql"  

2. 通过LOAD 'auto_explain' ;

这个只在当前SESSION生效,不需要重启数据库, 需要超级用户权限。

首先先恢复postgresql.conf的配置,去除前面的配置.然后重启数据库.

普通用户不允许加载auto_explain模块.(普通用户只允许加载$libdir/plugins目录下的模块,但是auto_explain即使拷贝到这个目录也不行)

digoal=> load 'auto_explain';  
ERROR:  access to library "auto_explain" is not allowed  
digoal=> \c digoal postgres  
You are now connected to database "digoal" as user "postgres".  
digoal=# load 'auto_explain';  
LOAD  
digoal=# set auto_explain.log_min_duration=0;  
SET  
digoal=# select * from tbl_user_info limit 2;  id | firstname | lastname |   corp     
----+-----------+----------+----------  1 | zhou1     | digoal1  | sky-mobi  2 | zhou2     | digoal2  | sky-mobi  
(2 rows)  

查看日志

2011-06-08 15:25:33.361 CST,"postgres","digoal",13968,"127.0.0.1:15445",4def23d5.3690,1,"SELECT",2011-06-08 15:25:09 CST,2/9,0,LOG,0  
0000,"duration: 0.048 ms  plan:  
Query Text: select * from tbl_user_info limit 2;  
Limit  (cost=0.00..0.04 rows=2 width=31)  ->  Seq Scan on tbl_user_info  (cost=0.00..183.00 rows=10000 width=31)",,,,,,,,,"psql"  

连接到digoal用户,这个LOAD的模块消失(后面会有解释).

digoal=# load 'auto_explain';  
LOAD  
digoal=# set session auto_explain.log_min_duration=0;  
SET  
digoal=# \c digoal digoal  
You are now connected to database "digoal" as user "digoal".  
digoal=> select * from tbl_user_info limit 3;  id | firstname | lastname |   corp     
----+-----------+----------+----------  1 | zhou1     | digoal1  | sky-mobi  2 | zhou2     | digoal2  | sky-mobi  3 | zhou3     | digoal3  | sky-mobi  
(3 rows)  

查看日志,没有auto_explain的输出.即使这里使用了session来定义这个参数的有效范围。

原因是session重新分配了,因为\c digoal digoal 相当于重新连接,backend也重新生成,如下.

digoal=> select * from pg_stat_activity;  datid | datname | procpid | usesysid | usename | application_name | client_addr | client_hostname | client_port |         backend_s  
tart         |          xact_start           |          query_start          | waiting |          current_query            
-------+---------+---------+----------+---------+------------------+-------------+-----------------+-------------+------------------  
-------------+-------------------------------+-------------------------------+---------+---------------------------------  16430 | digoal  |   14155 |    16423 | digoal  | psql             | 127.0.0.1   |                 |        5959 | 2011-06-08 15:31:  
32.794906+08 | 2011-06-08 15:31:40.616346+08 | 2011-06-08 15:31:40.616346+08 | f       | select * from pg_stat_activity;  
(1 row)  digoal=> \c digoal postgres  
You are now connected to database "digoal" as user "postgres".  
digoal=# select * from pg_stat_activity;  datid | datname | procpid | usesysid | usename  | application_name | client_addr | client_hostname | client_port |         backend_  
start         |          xact_start           |          query_start          | waiting |          current_query            
-------+---------+---------+----------+----------+------------------+-------------+-----------------+-------------+-----------------  
--------------+-------------------------------+-------------------------------+---------+---------------------------------  16430 | digoal  |   14161 |       10 | postgres | psql             | 127.0.0.1   |                 |        5961 | 2011-06-08 15:31  
:43.937297+08 | 2011-06-08 15:31:45.178005+08 | 2011-06-08 15:31:45.178005+08 | f       | select * from pg_stat_activity;  
(1 row)  

那么如何避免这样的情况发生呢? 答案是使用set role .

digoal=# load 'auto_explain';  
LOAD  
digoal=# set session auto_explain.log_min_duration=0;  
SET  
digoal=# set role digoal;  
SET  
digoal=> select * from tbl_user_info limit 3;  id | firstname | lastname |   corp     
----+-----------+----------+----------  1 | zhou1     | digoal1  | sky-mobi  2 | zhou2     | digoal2  | sky-mobi  3 | zhou3     | digoal3  | sky-mobi  
(3 rows) 

再看日志,已经有了 :

2011-06-08 15:29:30.011 CST,"postgres","digoal",14062,"127.0.0.1:5939",4def24bc.36ee,1,"SELECT",2011-06-08 15:29:00 CST,2/29,0,LOG,0  
0000,"duration: 0.031 ms  plan:  
Query Text: select * from tbl_user_info limit 3;  
Limit  (cost=0.00..0.05 rows=3 width=31)  ->  Seq Scan on tbl_user_info  (cost=0.00..183.00 rows=10000 width=31)",,,,,,,,,"psql"  

如果你不想看日志这么麻烦,想在client直接显示,也很方便,设置client_min_messages='log'就可以看到auto explain的输出了。

set client_min_messages='log';
set auto_explain.log_min_duration = 0;
set auto_explain.log_analyze = true;
set auto_explain.log_verbose = true;
set auto_explain.log_buffers = true;
set auto_explain.log_nested_statements = true;postgres=# do language plpgsql $$        
declare
begin
perform 1 from pg_class where oid=1;
end;
$$;LOG:  duration: 0.008 ms  plan:
Query Text: SELECT 1 from pg_class where oid=1
Index Only Scan using pg_class_oid_index on pg_catalog.pg_class  (cost=0.27..1.29 rows=1 width=4) (actual time=0.006..0.006 rows=0 loops=1)Output: 1Index Cond: (pg_class.oid = '1'::oid)Heap Fetches: 0Buffers: shared hit=2
DO

参考

1. man LOAD

2. man EXPLAIN

3. http://www.postgresql.org/docs/9.6/static/auto-explain.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/397335.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

判断请求来自手机还是PC

由于小程序和PC端用的是同一个后台 所以就需要判断请求是从哪里发过来的 在这里是利用Request Body 里面的user-agent 来判断 /** * 根据当前请求的特征,判断该请求是否来自手机终端,主要检测特殊的头信息,以及user-Agent这个header * * pa…

小旭的互联网营销之微信营销

11月1日,一篇题为《什么样的女黑客竟遭马云强东在双11联手封杀?》的文章,借助双11火热的关注效应,在短短两天时间内刷爆朋友圈。 该文章的女主角不仅外表靓丽,黑客技术更是惊艳:“作为美籍华人的Joanna在2015黑帽子会…

计算机专业录取分数及大学排名,计算机专业录取分数最高的大学有哪些?附排名前50大学名单...

高考结束之后,不少即将迎接高考的家长对于很多专业的录取情况都抱有很大的兴趣,都比较关心自己的理想专业大概能上哪些大学。今天,小编将为大家以山东高考计算机专业各大学录取分数进行排名,供下一届高考生参考。计算机专业作为近…

letsencrypt 自动续期不关闭nginx

为什么80%的码农都做不了架构师&#xff1f;>>> 已失效 corntab -e 5 0 1 * * /opt/letsencrypt/letsencrypt-auto --config /etc/letsencrypt/webroot.ini -d <domain> certonly && sudo service nginx reload/etc/letsencrypt/webroot.ini rsa-key…

loss低但精确度低_低光照图像增强网络-RetinexNet(model.py解析【2】)

论文地址&#xff1a;https://arxiv.org/pdf/1808.04560.pdf代码地址&#xff1a;https://github.com/weichen582/RetinexNet解析目录&#xff1a;https://zhuanlan.zhihu.com/p/88761829整个模型架构被实现为一个类&#xff1a;class lowlight_enhance(object):其构造函数实现…

计算机应用发表论文,计算机应用论文发表.docx

计算机应用论文发表1在工程项目管理中应用计算机技术存在的问题计算机软件是计算机运行的重要保障&#xff0c;一个好的计算机软件直接决定计算机技术在工程项目管理的高效应用。但由于市场上计算机软件种类繁多&#xff0c;质量好坏不一&#xff0c;质量好的价格高&#xff0c…

添加dubbo xsd的支持

使用dubbo时遇到问题&#xff1a; org.xml.sax.SAXParseException: schema_reference.4: Failed to read schema document http://code.alibabatech.com/schema/dubbo/dubbo.xsd, because 1) could not find the document; 2) the document could not be read; 3) the root ele…

byte数组穿换成pcm格式_形象地介绍DSD的编解码原理及和PCM的区别

一直有人不清楚DSD到底是啥原理&#xff0c;和MP3, FLAC, APE, WAV等基于PCM编码技术的音频格式又有啥区别。特意做了两张图说明一下。图一是是由很多黑点构成的蒙娜丽莎头像&#xff0c;点击看大图就知道是没有灰阶只有黑白两色。但是人眼是可以看到有丰富的灰阶的。这和DSD一…

最大熵对应的概率分布

最大熵对应的概率分布 最大熵定理 设 \(X \sim p(x)\) 是一个连续型随机变量&#xff0c;其微分熵定义为\[ h(X) - \int p(x)\log p(x) dx \]其中&#xff0c;\(\log\) 一般取自然对数 \(\ln\), 单位为 奈特&#xff08;nats&#xff09;。 考虑如下优化问题&#xff1a;\[ \b…

UBUNTU : Destination Host Unreachable

介绍我的系统的搭建的方式: WIN7 64 VMWARE STATION&#xff0c;方式是进行桥接的方式。最近突然出现了问题&#xff0c;Ubuntu ping 外网或者 PING WIN 7 的时候&#xff0c;出现 Destination Host Unreachable 的错误&#xff1b;想着去修改网卡的链接形式&#xff1a; 编辑…

焦作师范高等专科学校对口计算机分数线,焦作师范高等专科学校录取分数线2018...

焦作师范高等专科学校录取分数线20182018年 电子信息工程技术 理科 332 3602018年 物联网应用技术 文科 391 4082018年 物联网应用技术 理科 328 3692018年 学前教育 文科 388 4022018年 学前教育 理科 324 3512018年 移动应用开发 文科 02018年 移动应用开发 理科 305 3322018…

在Spring boot 配置过滤器(filter)

在spring boot 配置servlet filter 逻辑上与配置spring 是一样的。 不过相比spring 更加简化配置的难度。 这里只需要两步1 创建一个自定义顾虑器并继承spring filter 例如OncePerRequestFilterpublic class AuthenticationFilter extends OncePerRequestFilter{private final …

Flink之状态之状态存储 state backends

流计算中可能有各种方式来保存状态&#xff1a; 窗口操作使用 了KV操作的函数继承了CheckpointedFunction的函数当开始做checkpointing的时候&#xff0c;状态会被持久化到checkpoints里来规避数据丢失和状态恢复。选择的状态存储策略不同&#xff0c;会导致状态持久化如何和ch…

怎么把分开的pdf放在一起_糖和盐混在一起了要怎么分开?| 趣问万物

趣 问 万 物来源&#xff1a;把科学带回家撰文&#xff1a;Mirror如何分离糖和盐&#xff1f;图源&#xff1a;Pixabay小手一抖&#xff0c;不小心把糖(蔗糖)和盐(氯化钠)混在一块儿了该怎么办&#xff1f;趁着光棍节&#xff0c;就让我们吃饱了撑着研究研究把糖和盐拆散的N种方…

《JavaScript DOM编程艺术》笔记

1. 把<script>标签放到HTML文档的最后&#xff0c;<body>标签之前能使浏览器更快地加载页面。 2. nodeType的常见取值 元素节点(1) 属性节点(2) 文本节点(3) 3. <a href"http://www.baidu.com" οnclick"popUp(this.href);return false;"&g…

maven POM.xml内的标签大全详解

<project xmlns"http://maven.apache.org/POM/4.0.0" xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation"http://maven.apache.org/POM/4.0.0http://maven.apache.org/maven-v4_0_0.xsd"><!--父项目的坐标。如果…

常熟理工学院计算机考研,2018江苏专转本考生必看-常熟理工学院介绍

原标题&#xff1a;2018江苏专转本考生必看-常熟理工学院介绍这次轮到默默学介绍常熟理工学院啦&#xff01;今年常熟理工学院有个专转本的学生&#xff0c;也是默默学专转本视频课程考上常熟理工的一个学生&#xff0c;叫黄群超&#xff0c;当年专转本计算机也考了八九十分吧&…

.net中调用esb_大型ESB服务总线平台服务运行分析和监控预警实践

今天准备谈下ESB总线平台建设项目中的服务运行统计分析&#xff0c;服务心跳监测&#xff0c;服务监控预警方面的设计和实现。可以看到&#xff0c;在一个ESB服务总线平台上线后&#xff0c;SOA治理管控就变得相当重要&#xff0c;而这些运行监控分析本身也是提升ESB总线平台高…

使用Maven创建Web项目后,jsp引入静态文件提示报错。JSP 报错:javax.servlet.ServletException cannot be resolved to a type...

用maven创建多模块的web工程后&#xff0c;不同于直接创建普通的web工程。 1、在普通的web工程创建后&#xff0c;在项目中会有tomcat等服务器的jar包&#xff0c;这时创建JSP文件肯定是没有错的&#xff1b; 2、即使是使用maven创建的单模块的web工程&#xff0c;也会自动的在…

ES6之路第十三篇:Iterator和for...of循环

Iterator(遍历器)的概念 JavaScript 原有的表示“集合”的数据结构&#xff0c;主要是数组&#xff08;Array&#xff09;和对象&#xff08;Object&#xff09;&#xff0c;ES6 又添加了Map和Set。这样就有了四种数据集合&#xff0c;用户还可以组合使用它们&#xff0c;定义自…