目录
在 PostgreSQL 中,统计信息不仅是查询优化器制定执行计划的基础,也在数据库运行监控和自动维护中发挥着重要作用。本文将从统计信息的用途、产生方式和分类三个角度介绍统计信息。
1. 统计信息的作用
1.1. 查询优化
统计信息是查询优化器生成执行计划时最关键的参考依据。优化器依赖它来估算:
- 表或索引的大小与行数;
- 某列的值分布和空值比例;
- 哪种扫描方式 (顺序扫描、索引扫描或并行查询) 最具性价比;
- ...
没有准确的统计信息,优化器可能会选择低效的执行路径,导致查询性能显著下降。
1.2. 数据库运行状态监控
统计信息还可用于实时了解数据库运行状态,例如:
- 当前有哪些会话正在执行;
- 哪些表或索引被频繁访问;
- 系统资源是否存在负载不均或瓶颈;
这些信息对于数据库的调优、问题诊断与日常监控都非常重要。
1.3. 辅助 autovacuum 机制
PostgreSQL 中的 autovacuum 进程会根据统计信息判断某张表是否需要执行 VACUUM 或 ANALYZE 操作,从而在无需人工干预的前提下自动清理垃圾元组、更新统计数据,保持数据库的高效运转。
2. 统计信息的产生与分类
2.1. 表中元组数据的统计信息
这类统计信息主要通过执行 ANALYZE 命令生成,可作用于整个数据库、指定表或指定列。
其中关系级别的统计信息保存在 pg_class 系统表中:
- reltuples:记录表中元组的估计数量;
- relpages:记录表的页数;
- relallvisible:记录可见性映射中标记为“全部可见”的页面数量;
而列级别的统计信息则存储在 pg_statistic 系统表中,每条元组表示某一列的统计信息,例如:
- stanullfrac:该列中 NULL 值的比例;
- stawidth:列值的平均宽度;
还有其他字段记录值的分布、最常见值等。
这些统计信息的更新依赖于 ANALYZE 操作。可以由用户手动执行,或由 autovacuum 进程定期触发。所以这些数据具有滞后性,仅反映采样当时的表数据状态。它们的作用是:查询优化器会利用这些统计信息来评估执行计划的成本,从而选择最优的执行路径。
2.2. 数据库运行状态的统计信息
这部分统计信息分为两类:收集型与动态型,主要用于反映数据库的实时运行状态。这类统计信息的作用都是展示数据库的运行状态,用于数据库的运维监控。所以 PG 为上述这两类统计信息也定义了一系列的视图,它们以 pg_stat_ 或 pg_statio_ 开头。
2.2.1. 收集型统计信息
在 PG15 以前,PostgreSQL 的各类进程 (后端进程、归档进程、写入进程等) 在执行期间会调用相应的函数 (如 pgstat_report_stat、pgstat_send_archiver、pgstat_send_bgwriter) 将统计数据发送给专门的统计信息收集进程。而统计信息收集进程会将数据写入临时文件,通常位于 pg_stat_tmp/ 目录下 (该目录可通过 stats_temp_directory 参数配置) 。进程之间的通信采用 UDP 协议。PG 服务器关闭时,这些文件会被存放在 pg_stat/ 目录中,等 PG 再次重启时会重新加载这些文件中的信息,并再次将它们存放在 pg_stat_tmp/ 目录中。



从 PostgreSQL 15 开始,统计信息收集进程被移除了。这些统计信息不再会写入磁盘文件,而是直接存储在共享内存中。从而提升了效率,避免了文件系统 I/O 的额外开销。
但无论是磁盘文件 (PG15 之前) 还是共享内存 (PG15 起) ,这类统计信息都是定期更新的。因此它们仍具有一定的滞后性,只能反映某一时点的系统状态。它们的作用是:查询部分以 pg_stat_* 和 pg_statio_* 命名的视图时,实质上就是从文件或共享内容中读取这些信息。
2.2.2. 收集型统计信息视图
- pg_stat_all_tables、pg_stat_sys_tables、pg_stat_user_tables:
- 显示当前数据库中 全部表/系统表/用户表 的使用统计信息;
- 比如顺序扫描的次数、索引扫描的次数、估计的死元组数量等;
- 显示当前数据库中 全部表/系统表/用户表 的使用统计信息;
- pg_stat_xact_all_tables、pg_stat_xact_sys_tables、pg_stat_xact_user_tables:
- 同上,但显示的是当前事务周期内的统计数据;
- 同上,但显示的是当前事务周期内的统计数据;
- pg_stat_all_indexes、pg_stat_sys_indexes、pg_stat_user_indexes:
- 显示当前数据库中 全部索引/系统索引/用户索引 访问的统计信息;
- 比如该索引被用于扫描的总次数、索引扫描读取的元组数;
- 显示当前数据库中 全部索引/系统索引/用户索引 访问的统计信息;
- pg_statio_all_tables、pg_statio_sys_tables、pg_statio_user_tables:
- 显示当前数据库中 全部表/系统表/用户表 物理读写的统计信息;
- 比如从磁盘读取的数据块数量、从磁盘读取的 TOAST 块数、TOAST 索引的缓存命中数;
- 显示当前数据库中 全部表/系统表/用户表 物理读写的统计信息;
- pg_statio_all_indexes、pg_statio_sys_indexes、pg_statio_user_indexes:
- 显示当前数据库中 全部索引/系统索引/用户索引 物理读写的统计信息;
- 显示当前数据库中 全部索引/系统索引/用户索引 物理读写的统计信息;
- pg_statio_all_sequences、pg_statio_sys_sequences、pg_statio_user_sequences:
- 显示当前数据库中 全部序列/系统序列/用户序列 物理读写的统计信息;
- 显示当前数据库中 全部序列/系统序列/用户序列 物理读写的统计信息;
- pg_stat_database:
- 显示各个数据库的整体活动情况;
- 比如从磁盘和缓存中读取的数据块数量,已提交或回滚的事务数量等;
- 显示各个数据库的整体活动情况;
- pg_stat_archiver:
- 显示归档程序产生的数据 (而不是归档程序当前的运行状态) ;
- 该视图最多包含一行记录;
- 显示归档程序产生的数据 (而不是归档程序当前的运行状态) ;
- pg_stat_bgwriter:
- 显示后台写进程产生的数据(而不是后台写进程当前的运行状态);
- 该视图最多包含一行记录;
- 显示后台写进程产生的数据(而不是后台写进程当前的运行状态);
- pg_stat_database_conflicts:
- 显示主备复制过程中的冲突情况;
- 显示主备复制过程中的冲突情况;
- pg_stat_user_functions:
- 显示有关用户自定义函数执行的统计信息;
- 比如调用次数、执行时间等;
- 显示有关用户自定义函数执行的统计信息;
- pg_stat_xact_user_functions:
- 同上,但显示的是当前事务周期内的统计数据;
- 同上,但显示的是当前事务周期内的统计数据;
- pg_stat_slru:
- 显示 SLRU 缓存机制的运行信息;
- 比如从 SLRU 缓存中命中的页数、从磁盘读取的页数、写入磁盘的页数等;
- 显示 SLRU 缓存机制的运行信息;
2.2.3. 动态统计信息
动态统计信息来自实时更新的服务器内存。这些数据的采集不依赖统计信息收集进程,直接由内核机制维护。所以这些数据具备实时性,可反映数据库“此时此刻”的运行状态。这类统计信息的作用是:查询部分 pg_stat_* 和 pg_statio_* 视图时,本质上就是直接从内存获取这些数据。
2.2.4. 动态统计信息视图
- pg_stat_activity:
- 显示当前所有连接的运行状态;
- 比如正在执行的 SQL、连接用户、会话状态、等待事件等;
- 显示当前所有连接的运行状态;
- pg_stat_replication:
- 显示从当前主库发出的所有流复制连接的信息,每一条记录对应一个连接到主库的备库 (主库视角) ;
- 显示从当前主库发出的所有流复制连接的信息,每一条记录对应一个连接到主库的备库 (主库视角) ;
- pg_stat_wal_receiver:
- 显示当前备库的 WAL 接收进程的状态信息,仅在备库上有数据 (备库视角) ;
- 该视图最多包含一行记录;
- 显示当前备库的 WAL 接收进程的状态信息,仅在备库上有数据 (备库视角) ;
- pg_stat_subscription:
- 显示订阅的状态信息;
- 显示订阅的状态信息;
- pg_stat_ssl:
- 显示连接上的 SSL 使用的情况;
- 显示连接上的 SSL 使用的情况;
- pg_stat_gssapi:
- 显示连接上的 GSSAPI 使用的情况;
- 显示连接上的 GSSAPI 使用的情况;
- 进度报告相关视图:
- pg_stat_progress_analyze:
- 显示正在执行中的 analyze 命令的进度;
- 显示正在执行中的 analyze 命令的进度;
- pg_stat_progress_create_index:
- 显示正在执行中的 create index 命令的进度;
- 显示正在执行中的 create index 命令的进度;
- pg_stat_progress_vacuum:
- 显示正在执行中的 vacuum 命令的进度;
- 显示正在执行中的 vacuum 命令的进度;
- pg_stat_progress_cluster:
- 显示正在执行中的 cluster 命令的进度;
- 显示正在执行中的 cluster 命令的进度;
- pg_stat_progress_copy (PG14 新增) :
- 显示正在执行中的 copy 命令的状态;
- 显示正在执行中的 copy 命令的状态;
- pg_stat_progress_basebackup:
- 显示正在执行中的 basebackup 的状态;
- 显示正在执行中的 basebackup 的状态;
- pg_stat_progress_analyze:
2.3. 插件提供的统计信息
除了核心统计信息机制,PostgreSQL 还支持通过插件扩展统计功能。例如,pg_stat_statements 插件会记录 SQL 语句的执行频率、耗时、命中率等,并以 pg_stat_statements 视图呈现。
- pg_stat_statements 如何生成统计信息:通过 hook 机制捕获各类 SQL 语句的执行信息,具体来说是通过 pgss_ExecutorStart 和 pgss_ExecutorEnd 函数。所以这种统计信息也是准确的,这对于 SQL 调优和热点查询分析极为有用。
- pg_stat_statements 统计信息的存储:PG 在运行期间,pgss_ExecutorEnd 函数会将捕获的执行信息存储到共享内存中,但 SQL 的原始文本不会存放在共享内存中,而是以文件形式单独存储在磁盘上,文件名为 pg_stat_tmp/pgss_query_texts.stat;
3. 小结
统计信息贯穿 PostgreSQL 数据库的查询优化、运行监控等多个关键环节。理解其分类、来源与作用,不仅能帮助用户写出更高效的 SQL,还能为数据库运维人员提供更具洞察力的分析视角。无论是手动调优,还是自动化运维,统计信息都是不可或缺的基础组件。
需要注意的是,尽管我们将表数据的采样信息、后台进程生成的运行指标,以及内存中实时状态一并称为“统计信息”,但它们在 PostgreSQL 中的实际作用却各不相同:有的服务于优化器做出执行计划决策,有的反映数据库的整体负载趋势,也有的用于实时监控活跃会话状态。在不同的使用场景下,理解它们的生成机制与适用语境,是有效利用统计信息的前提。




