PostgreSQL pg_stat_statements 性能分析利器(一)定位慢查询

5 阅读3分钟

PostgreSQL 使用越来越广泛,大家在使用的过程中,是如何排查慢SQL的呢?

今天介绍一下慢SQL排查利器:pg_stat_statements。

本系列文章使用的PostgreSQL版本都是18

什么是 pg_stat_statements

它是一个单独的模块,作用是统计所有语句的执行情况,就是说它的结果是统计后的结果,不是流水的日志。

最常规的作用是,统计SQL的执行耗时以及相同SQL的执行次数等等。

使用条件

  • 修改配置文件postgresql.conf,配置shared_preload_libraries = 'pg_stat_statements',改完配置文件,是需要重启服务的。
  • 查询标识符计算,这个配置项默认是auto,不用管即可。
  • 为特定数据库启动统计跟踪,CREATE EXTENSION pg_stat_statements

参考配置如下

# postgresql.conf

shared_preload_libraries = 'pg_stat_statements'		# (change requires restart)

#compute_query_id = auto

慢SQL定位

有了上面的基础,具体怎么用呢?

其实就是查询pg_stat_statements视图,分析其中字段的值,来判断具体问题出在哪里。里面有很多的字段,初一上来就分析,很容易懵。

下面就先给出一个初级模板,来查询比较耗时的SQL。大家可以根据需求修改查询字段和排序条件。

执行逻辑是按总耗时倒排取前10条,这样就取到了最耗时的10条SQL。因为是统计的结果,耗时最高的并不一定单个SQL耗时,还有可能是执行次数多,累加起来比较高。所以根据情况再参考callsmean_exec_timemax_exec_time等字段。

SELECT
    queryid,
    query,
    calls,
    round(total_exec_time::numeric/1000, 2) AS total_time_s,
    round(mean_exec_time::numeric, 2) AS mean_time_ms,
    round(max_exec_time::numeric, 2) AS max_time_ms,
    round(min_exec_time::numeric, 2) as min_time_ms 
FROM pg_stat_statements
ORDER BY total_exec_time DESC
LIMIT 10;
  • query:归一化的SQL语句。
  • calls:执行次数。
  • total_exec_time:总耗时,单位是毫秒。
  • mean_exec_time:平均耗时。
  • max_exec_time:最大耗时,即多次查询统计的最大值。

实例

分析一个查询结果实例。为了方便展示,只读取了关键字段。

你可以先暂停,自己先分析一遍,再看我给出的分析。

calls|total_time_s|mean_time_ms|max_time_ms|min_time_ms|
-----+------------+------------+-----------+-----------+
    5|       12.02|     2403.06|    4003.84|    1004.98|
    1|        8.01|     8008.47|    8008.47|    8008.47|
  • 第一条,总耗时12秒,但是执行了5次,最多的一次4秒,最少的一次1秒。是由于次数多推高了耗时。
  • 第二条,总耗时8秒,却执行了1次。说明单次执行比第一条更耗时。

扩展

对模板SQL的排序字段稍加改动就可以实现以下目的:

  • 平均耗时最高的 TOP 10 SQL
  • 执行次数最多的 TOP 10 SQL

总结

本篇是pg_stat_statements系列第一篇,简单介绍了它是什么、使用条件有哪些。

再给出了一个查询示例,可以直接用来定位慢SQL。

怎么样,是不是感觉入门很简单,学到了就赶紧练起来吧!

参考

PostgreSQL: Documentation: 16: F.32. pg_stat_statements — track statistics of SQL planning and execution