PostgreSQL 18 预览: 清理和分析关系表的累积统计信息

John Doe 四月 16, 2025

你想不想知道 PostgreSQL 在每个表上面,进行清理和分析所花费的时间?现在,PostgreSQL 提供了清理和分析关系表的累积统计信息。

草原上的一头大象

特性提交日志

跟踪每个表在 [自动] 清理和 [自动] 分析中累计花费的时间。

本次提交在表关系的统计信息中新增了四个字段,用于汇总对每个表关系执行各项操作所花费的时间:

  • total_vacuum_time,用于记录手动清理操作所花费的时间。
  • total_autovacuum_time,用于记录自动清理守护进程执行清理操作所花费的时间。
  • total_analyze_time,用于记录手动分析操作所花费的时间。
  • total_autoanalyze_time,用于记录自动清理守护进程执行分析操作所花费的时间。

借助相关的 “计数” 字段,用户可以利用这些新增字段计算出执行这些操作的平均耗时。

讨论:https://postgr.es/m/CAA5RZ0uVOGBYmPEeGF2d1B_67tgNjKx_bKDuL+oUftuoz+=Y1g@mail.gmail.com

示例

PostgreSQL 的统计系统几乎在每次版本发布时都会增加更多详细信息,PostgreSQL 18 也不例外。

在 PostgreSQL 17 中查看pg_stat_all_tables(或pg_stat_user_tables)时,它是这样的:

postgres=# select version();
                                                           version
-----------------------------------------------------------------------------------------------------------------------------
 PostgreSQL 17.2 on x86_64-pc-linux-gnu, compiled by gcc (GCC) 14.2.1 20250110 (Red Hat 14.2.1-7), 64-bit
(1 row)

postgres=# \d pg_stat_all_tables 
                      View "pg_catalog.pg_stat_all_tables"
       Column        |           Type           | Collation | Nullable | Default
---------------------+--------------------------+-----------+----------+---------
 relid               | oid                      |           |          | 
 schemaname          | name                     |           |          | 
 relname             | name                     |           |          | 
 seq_scan            | bigint                   |           |          | 
 last_seq_scan       | timestamp with time zone |           |          | 
 seq_tup_read        | bigint                   |           |          | 
 idx_scan            | bigint                   |           |          | 
 last_idx_scan       | timestamp with time zone |           |          | 
 idx_tup_fetch       | bigint                   |           |          | 
 n_tup_ins           | bigint                   |           |          | 
 n_tup_upd           | bigint                   |           |          | 
 n_tup_del           | bigint                   |           |          | 
 n_tup_hot_upd       | bigint                   |           |          | 
 n_tup_newpage_upd   | bigint                   |           |          | 
 n_live_tup          | bigint                   |           |          | 
 n_dead_tup          | bigint                   |           |          | 
 n_mod_since_analyze | bigint                   |           |          | 
 n_ins_since_vacuum  | bigint                   |           |          | 
 last_vacuum         | timestamp with time zone |           |          | 
 last_autovacuum     | timestamp with time zone |           |          | 
 last_analyze        | timestamp with time zone |           |          | 
 last_autoanalyze    | timestamp with time zone |           |          | 
 vacuum_count        | bigint                   |           |          | 
 autovacuum_count    | bigint                   |           |          | 
 analyze_count       | bigint                   |           |          | 
 autoanalyze_count   | bigint                   |           |          | 

其中已经包含了 [自动] 清理和 [自动] 分析的统计信息,但没有关于系统在清理和分析操作上总共花费了多少时间的信息。现在,这个信息可以获取到了:

postgres=# select version();
                              version
--------------------------------------------------------------------
 PostgreSQL 18devel on x86_64-linux, compiled by gcc-14.2.1, 64-bit
(1 row)

postgres=# \d pg_stat_all_tables 
                        View "pg_catalog.pg_stat_all_tables"
         Column         |           Type           | Collation | Nullable | Default
------------------------+--------------------------+-----------+----------+---------
 relid                  | oid                      |           |          | 
 schemaname             | name                     |           |          | 
 relname                | name                     |           |          | 
 seq_scan               | bigint                   |           |          | 
 last_seq_scan          | timestamp with time zone |           |          | 
 seq_tup_read           | bigint                   |           |          | 
 idx_scan               | bigint                   |           |          | 
 last_idx_scan          | timestamp with time zone |           |          | 
 idx_tup_fetch          | bigint                   |           |          | 
 n_tup_ins              | bigint                   |           |          | 
 n_tup_upd              | bigint                   |           |          | 
 n_tup_del              | bigint                   |           |          | 
 n_tup_hot_upd          | bigint                   |           |          | 
 n_tup_newpage_upd      | bigint                   |           |          | 
 n_live_tup             | bigint                   |           |          | 
 n_dead_tup             | bigint                   |           |          | 
 n_mod_since_analyze    | bigint                   |           |          | 
 n_ins_since_vacuum     | bigint                   |           |          | 
 last_vacuum            | timestamp with time zone |           |          | 
 last_autovacuum        | timestamp with time zone |           |          | 
 last_analyze           | timestamp with time zone |           |          | 
 last_autoanalyze       | timestamp with time zone |           |          | 
 vacuum_count           | bigint                   |           |          | 
 autovacuum_count       | bigint                   |           |          | 
 analyze_count          | bigint                   |           |          | 
 autoanalyze_count      | bigint                   |           |          | 
 total_vacuum_time      | double precision         |           |          | 
 total_autovacuum_time  | double precision         |           |          | 
 total_analyze_time     | double precision         |           |          | 
 total_autoanalyze_time | double precision         |           |          | 

为了实际查看这些信息,我们创建一个小表并插入数据:

create table t ( a int, b text);

insert into t select i, i::text from generate_series(1,1000000) i;

这会触发自动清理(由于autovacuum_naptime参数的设置,你可能需要等待长达一分钟才能看到结果),你可以获取到自动清理和自动分析所花费的总时间(以毫秒为单位):

select last_autovacuum
     , last_autoanalyze
     , total_autovacuum_time
     , total_autoanalyze_time 
   from pg_stat_all_tables 
 where relname = 't';

        last_autovacuum        |       last_autoanalyze        | total_autovacuum_time | total_autoanalyze_time 
-------------------------------+-------------------------------+-----------------------+------------------------
 2025-04-12 11:12:09.809252+08 | 2025-04-12 11:12:09.942748+08 |                   187 |                    134
(1 row)

如果你手动触发清理或分析操作,也会出现同样的情况:

select last_vacuum
     , last_analyze
     , total_vacuum_time
     , total_analyze_time 
   from pg_stat_all_tables 
 where relname = 't';
 last_vacuum | last_analyze | total_vacuum_time | total_analyze_time 
-------------+--------------+-------------------+--------------------
             |              |                 0 |                  0
(1 row)

analyze t;

select last_vacuum
     , last_analyze
     , total_vacuum_time
     , total_analyze_time 
   from pg_stat_all_tables 
 where relname = 't';
 last_vacuum |         last_analyze          | total_vacuum_time | total_analyze_time 
-------------+-------------------------------+-------------------+--------------------
             | 2025-04-12 11:23:07.102182+08 |                 0 |                 52
(1 row)

vacuum t;

select last_vacuum
     , last_analyze
     , total_vacuum_time
     , total_analyze_time 
   from pg_stat_all_tables 
 where relname = 't';
          last_vacuum          |         last_analyze          | total_vacuum_time | total_analyze_time 
-------------------------------+-------------------------------+-------------------+--------------------
 2025-04-12 11:23:12.286613+08 | 2025-04-12 11:23:07.102182+08 |                 1 |                 52

这非常有助于确定 [自动] 清理和 [自动] 分析花费时间最多的那些表关系。

非常不错的体验。感谢社区的所有相关人员。

参考

提交日志:https://git.postgresql.org/pg/commitdiff/30a6ed0ce4bb18212ec38cdb537ea4b43bc99b83