pg的sql统计信息,慢查询等

背景

数据库运维过程中,dba都比较关注sql的执行时间。研发在数据库应用开发上,速度慢的sql比比皆是,很多速度很慢都是sql写得不好,效率不高,执行过程中也会造成数据库的负载过大。比如无用的去重,无效的条件,不必要的子查询,sql用不上的索引。而对于这些不符合要求的sql,首先要去把这些sql找出来。

措施

pg数据库提供了统计信息的功能来查找,下面介绍两种办法:

  • 修改日志参数,记录超过指定时间的sql,以及当时的执行时间
  • 通过pg_stat_statements统计

修改日志参数

log_min_duration_statement:从log中找出执行超过一定时间的sql。这个参数是设置执行最小多长时间的sql输出到log,例如输出执行超过3秒的sql,可以设置log_min_duration_statement = 3s。这个参数设置为-1是无效,默认为-1。设置为0是输出所有的sql,但这样会增加服务器的负担,一般不要设置太低的值。

auto_explain功能:在Postgresql8.4版本后新增了该功能。默认这个功能是不可用的,需要配置如下。这样系统在执行的时候遇到超过2秒的SQL的话,,会自动把sql输出到log,这样看log就更容易找到问题点了。

shared_preload_libraries = 'auto_explain'
custom_variable_classes = 'auto_explain'   #PostgreSQL9.2版本后此参数已取消,不需要设置
auto_explain.log_min_duration = 2s

实际log查看:

< 2019-11-12 15:40:30.284 CST > 日志:  执行时间: 3048.397 ms 语句: SELECT * FROM indexedresult WHERE searchtitle LIKE '%好%' ORDER BY  searchtitle

加载pg_stat_statements模块

pg_stat_statements模块提供了一种方法,用于跟踪所有由服务器执行的sql语句的统计,例如,语句总调用次数,总执行时间,从内存中读取的块数,从磁盘读取的块数等信息。在添加或删除模块pg_stat_statements模块时,需要额外的共享内存,所以必须重启数据库。pg_stat_statements模块加载会消耗部分的内存,可以通过pg_stat_statements.max * track_activity_query_size来计算。这个值是比较小的,假如pg_stat_statements.max 值为 10000, track_activity_query_size值为4096,也就消耗了40M内存。

参考配置如下:

shared_preload_libraries = 'pg_stat_statements '
track_activity_query_size = 4096                #SQL文本的最大大小,4K
custom_variable_classes = 'pg_stat_statements '  #PostgreSQL9.2版本后此参数已取消,不需要设置
pg_stat_statements.max = 10000                #跟踪模块中的语句的最大数目
pg_stat_statements.track = all

参数配置好后,需要重启数据库。注意该模块是区分数据库的,不是全局共享的。如果无法查询,可能需要在对应的数据库下面加载pg_stat_statements模块。运行如下语句:

CREATE EXTENSION pg_stat_statements;

配置好pg_stat_statements模块后,经过一段时间的运行,我们就可以通过pg_stat_statements视图来统计效率低的SQL,语句如下:

--查询语句总调用次数大于10次,平均运行时间倒序的SQL
SELECT t.userid,
        t.dbid,
        t.query || ';',
        t.calls,
        t.total_time,
        t.rows,
        t.total_time / t.calls
  FROM pg_stat_statements t
 WHERE (t.calls IS NOT NULL OR t.calls <> 0)
   AND t.query !~ '^COPY|<insufficient privilege'
   AND t.calls > 10
 ORDER BY 7 DESC;

总结

上面两种方法可以根据实际业务需要来进行,比如仅仅需要查看问题sql的情况可以用第一种,如果需要深入分析sql的类别,执行次数,执行时间等更丰富的信息可以采用第二种方式,根据调用的次数来设计缓存也是非常重要的依据。

posted @ 2019-11-12 17:41  echao  阅读(2890)  评论(0编辑  收藏  举报