PostgreSQL 插件 pg_stat_statements

1. pg_stat_statements 说明

pg_stat_statements 是 PostgreSQL 数据库的一个开源插件,简称 pgss,用于跟踪数据库中 SQL 语句的执行计划,统计执行时间和资源消耗。

2. pg_stat_statements 参数

  • pg_stat_statements.max,跟踪的最大 SQL 语句数量,最小值 100, 最大值 INT_MAX,默认值 5000
  • pg_stat_statements.track,表示跟踪什么类型的 SQL 语句,可选值为 none,top,all,默认值为 top
  • pg_stat_statements.track_utility,表示是否跟踪 utility 语句,可选值 true,false,默认值 true
  • pg_stat_statements.track_planning,表示是否跟踪执行计划耗时,可选值 true,false,默认值 false
  • pg_stat_statements.save,表示当数据库关机时,是否保存统计信息,可选值 true,false,默认值 true

3. pg_stat_statements 使用方法

在 postgresql.conf 文件中设置参数,在数据库启动时加载 pgss,如下:

shared_preload_libraries = 'pg_stat_statements'

连接到数据库创建扩展 pg_stat_statements,如下:

create extension pg_stat_statements;

创建扩展之后,数据库中会创建一个视图,名为 pg_stat_statements,该视图中保存了跟踪到的 SQL 统计信息,查询视图如下:

select * from pg_stat_statements;

通常的查询如下,包含用户ID,数据库ID,查询ID,查询SQL,执行计划,执行计划耗时(最小,最大,平均),调用次数,总的执行耗时,最小执行耗时,最大执行耗时,平均执行耗时,涉及的行数,共享页相关的情况(命中数量,读取数量,脏页数量,写回磁盘的数量),本地页相关的情况(命中数量,读取数量,脏页数量,写回磁盘的数量),临时页读写情况,WAL日志相关情况(WAL 记录数量,FPI数量,字节数量)。

userid              | 10
dbid                | 13580
queryid             | 7402507857450412395
query               | insert into t1 select * from t1
plans               | 0
total_plan_time     | 0
min_plan_time       | 0
max_plan_time       | 0
mean_plan_time      | 0
stddev_plan_time    | 0
calls               | 11
total_exec_time     | 20.379245
min_exec_time       | 0.062924
max_exec_time       | 9.044859
mean_exec_time      | 1.8526586363636364
stddev_exec_time    | 2.7114879328796
rows                | 4094
shared_blks_hit     | 4155
shared_blks_read    | 2
shared_blks_dirtied | 18
shared_blks_written | 18
local_blks_hit      | 0
local_blks_read     | 0
local_blks_dirtied  | 0
local_blks_written  | 0
temp_blks_read      | 0
temp_blks_written   | 0
blk_read_time       | 0
blk_write_time      | 0
wal_records         | 4094
wal_fpi             | 0
wal_bytes           | 257922

重置统计数据:

select pg_stat_statements_reset();

4. pg_stat_statements 内部实现原理

4.1 数据如何获取

通过在加载插件时安装 hook 函数,在 SQL 执行的不同阶段获取对应的数据。

主要 hook 函数如下:

/*
     * Install hooks.
     */
    prev_shmem_startup_hook = shmem_startup_hook;
    shmem_startup_hook = pgss_shmem_startup;
    prev_post_parse_analyze_hook = post_parse_analyze_hook;
    post_parse_analyze_hook = pgss_post_parse_analyze;
    prev_planner_hook = planner_hook;
    planner_hook = pgss_planner;
    prev_ExecutorStart = ExecutorStart_hook;
    ExecutorStart_hook = pgss_ExecutorStart;
    prev_ExecutorRun = ExecutorRun_hook;
    ExecutorRun_hook = pgss_ExecutorRun;
    prev_ExecutorFinish = ExecutorFinish_hook;
    ExecutorFinish_hook = pgss_ExecutorFinish;
    prev_ExecutorEnd = ExecutorEnd_hook;
    ExecutorEnd_hook = pgss_ExecutorEnd;
    prev_ProcessUtility = ProcessUtility_hook;
    ProcessUtility_hook = pgss_ProcessUtility;

4.2 数据如何存储

基于共享内存的 hash 表 pgss_hash 存储数据,在加载插件时计算需要的共享内存大小。

_PG_init()
    RequestAddinShmemSpace()

当参数 pg_stat_statements.save 设置为 on 时,关闭数据库会将 pgss 的统计信息存储在文件中,启动数据库时从文件读取到共享内存里。

文章评论

0条评论