选择 打开 改范围 完整检索页

pgsql.cc 提供对 postgresql.org 官网内容的中文翻译,由 Pigsty 团队维护。

受支持版本: 当前版本 (18) / 17 / 16 / 15 / 14
测试与开发版本: 19 / devel
不受支持的版本: 13 / 12 / 11 / 10 / 9.6 / 9.5 / 9.4 / 9.3 / 9.2 / 9.1 / 9.0
历史版本PostgreSQL 9.0 已于 2015 年 10 月结束社区维护,本页译文保留供仍在使用旧版本的读者参考。新系统请看当前版本

27.2. 统计收集器 #

PostgreSQL统计收集器是一个支持收集和报告服务器活动信息的子系统。目前,收集器可以按磁盘块和单行两种方式统计对表和索引的访问。它还跟踪每个表中的总行数,以及每个表最近一次清理和分析的时间。它还可以统计对用户定义函数的调用次数以及在每个函数中花费的总时间。

PostgreSQL还支持报告其他服务器进程当前正在执行的确切命令。此功能独立于收集器进程。

27.2.1. 统计信息收集配置 #

由于收集统计信息会增加查询执行的开销,因此可以配置系统是否收集信息。这由通常在postgresql.conf中设置的配置参数控制(有关设置配置参数的详细信息,请参阅第 18 章)。

参数track_counts控制是否收集关于表和索引访问的统计信息。

参数track_functions启用对用户定义函数使用的跟踪。

参数track_activities启用对任意服务器进程当前执行命令的监控。

通常,这些参数会设置在postgresql.conf中,以便它们适用于所有服务器进程,但也可以在单个会话中使用SET命令打开或关闭它们。(为防止普通用户隐藏其活动不被管理员发现,只有超级用户才能使用SET更改这些参数。)

统计收集器通过临时文件与需要信息的后端(包括自动清理)通信。这些文件存储在pg_stat_tmp子目录中。当 postmaster 关闭时,统计数据的一份永久副本会存储在global子目录中。为提高性能,可以把参数stats_temp_directory指向基于 RAM 的文件系统,以减少物理 I/O 需求。

27.2.2. 查看收集到的统计信息 #

若干预定义视图(列于表 27.1中)可用于展示统计收集的结果。另外,也可以使用底层的统计函数构建自定义视图。

在使用统计信息监控当前活动时,重要的是要认识到这些信息不会即时更新。每个服务器进程在即将进入空闲之前把新的统计计数传送给收集器;因此仍在进行中的查询或事务不会影响显示的总数。此外,收集器本身最多每PGSTAT_STAT_INTERVAL毫秒(默认 500,除非构建服务器时更改)发出一次新报告。因此,显示的信息滞后于实际活动。不过,track_activities收集的当前查询信息总是最新的。

另一个重要点是,当要求服务器进程显示这些统计信息中的任何一种时,它会先取回收集器进程最近发出的报告,然后在当前事务结束之前,对所有统计视图和函数一直使用这一快照。因此,只要你继续当前事务,统计信息就会显示静态信息。类似地,在事务中第一次请求这类当前查询信息时,就会收集所有会话当前查询的信息,并且在整个事务期间显示的都是同一份信息。这是一个特性,而不是一个错误,因为它允许你对统计信息执行多个查询并对结果做关联,而不必担心数字在你眼前变化。但如果希望每个查询都看到新的结果,请确保在任何事务块之外执行这些查询。或者,也可以调用pg_stat_clear_snapshot(),它会丢弃当前事务的统计快照(如果有)。下一次使用统计信息时,就会获取一个新的快照。

表 27.1. 标准统计视图

View Name Description
pg_stat_activity 每个服务器进程一行,显示数据库 OID、数据库名、进程ID、用户 OID、用户名、客户端地址和端口号,服务器进程、当前事务和当前查询开始执行的时间,进程的等待状态,以及当前查询的文本。报告当前查询数据的各列只有在参数track_activities未被关闭时才可用。此外,只有当查看该视图的用户是超级用户或与被报告进程的属主是同一用户时,这些列才可见。
pg_stat_bgwriter 仅一行,显示来自后台写进程的集簇范围统计:计划内检查点的数量、被请求的检查点的数量、由检查点和后台清理扫描写出的缓冲区数,以及后台写进程因写出过多缓冲区而中止清理扫描的次数。还包括关于共享缓冲池的统计,包括由后端进程(即非后台写进程)写出的缓冲区数和分配的总缓冲区数。
pg_stat_database 每个数据库一行,显示数据库 OID、数据库名、连接到该数据库的活动服务器进程数、该数据库中已提交和已回滚的事务数、读取的磁盘块总数、缓冲区命中总数(即因在缓冲缓存中找到块而避免的块读请求数),以及返回、获取、插入、更新和删除的行数。
pg_stat_all_tables 当前数据库中的每个表(包括 TOAST 表)一行,显示表 OID、模式和表名、发起的顺序扫描次数、顺序扫描取出的活行数、发起的索引扫描次数(对该表所属的所有索引)、索引扫描取出的活行数、行插入、更新和删除的次数、HOT 更新(即无单独索引更新)的次数、活行数和死行数、该表最近一次手工清理的时间、最近一次被自动清理守护进程清理的时间、最近一次手工分析的时间,以及最近一次被自动清理守护进程分析的时间。
pg_stat_sys_tables pg_stat_all_tables相同,但只显示系统表。
pg_stat_user_tables pg_stat_all_tables相同,但只显示用户表。
pg_stat_all_indexes 当前数据库中的每个索引一行,显示表和索引 OID、模式、表和索引名、在该索引上发起的索引扫描次数、索引扫描返回的索引条目数,以及使用该索引的简单索引扫描取出的活表行数。
pg_stat_sys_indexes pg_stat_all_indexes一样,但只显示系统表上的索引。
pg_stat_user_indexes pg_stat_all_indexes一样,但只显示用户表上的索引。
pg_statio_all_tables 当前数据库中的每个表(包括 TOAST 表)一行,显示表 OID、模式和表名、从该表读取的磁盘块数、缓冲区命中数、该表所有索引的磁盘块读取数和缓冲区命中数、该表辅助 TOAST 表(若有)的磁盘块读取数和缓冲区命中数,以及 TOAST 表索引的磁盘块读取数和缓冲区命中数。
pg_statio_sys_tables Same as pg_statio_all_tables, except that only system tables are shown.
pg_statio_user_tables Same as pg_statio_all_tables, except that only user tables are shown.
pg_statio_all_indexes 当前数据库中的每个索引一行,显示表和索引 OID、模式、表和索引名,以及该索引中的磁盘块读取数和缓冲区命中数。
pg_statio_sys_indexes pg_statio_all_indexes一样,但只显示系统表上的索引。
pg_statio_user_indexes pg_statio_all_indexes一样,但只显示用户表上的索引。
pg_statio_all_sequences 当前数据库中的每个序列对象一行,显示序列 OID、模式和序列名,以及该序列中的磁盘块读取数和缓冲区命中数。
pg_statio_sys_sequences pg_statio_all_sequences一样,但只显示系统序列。(目前没有定义任何系统序列,因此该视图总是空的。)
pg_statio_user_sequences pg_statio_all_sequences一样,但只显示用户序列。
pg_stat_user_functions 对所有被跟踪的函数,显示函数 OID、模式、名称、调用次数、总时间和自身时间。自身时间是花在该函数本身的时间,总时间包括花在它调用的函数中的时间。时间值以毫秒计。

每个索引的统计信息对于判断哪些索引正在被使用以及它们有多有效尤其有用。

PostgreSQL 8.1 开始,索引既可以被直接使用,也可以通过位图扫描使用。在位图扫描中,多个索引的输出可以通过 AND 或 OR 规则组合;因此在使用位图扫描时,很难把各个堆行取出与特定索引关联起来。因此,位图扫描会增加它所用索引的pg_stat_all_indexes.idx_tup_read计数,并增加该表的pg_stat_all_tables.idx_tup_fetch计数,但不影响pg_stat_all_indexes.idx_tup_fetch

注意

PostgreSQL 8.1 之前,idx_tup_readidx_tup_fetch计数基本上总是相等的。现在,即使不考虑位图扫描,它们也可能不同,因为idx_tup_read统计从索引中取出的索引条目,而idx_tup_fetch统计从表中取出的活行;如果用索引取出了任何死行或尚未提交的行,后者就会更小。

pg_statio_视图主要用于判断缓冲区缓存的有效性。 如果实际磁盘读取次数远少于缓冲区命中次数,缓存就能满足大多数读取请求,而无需调用内核。 不过,这些统计信息并不能反映全部情况:由于PostgreSQL处理磁盘 I/O 的方式, 不在PostgreSQL缓冲区缓存中的数据仍可能驻留在内核的 I/O 缓存中, 因而仍可在不执行物理读取的情况下取得。对于希望更详细地了解PostgreSQL I/O 行为的用户, 建议将PostgreSQL统计收集器与能够深入查看内核 I/O 处理情况的操作系统工具结合使用。

也可以通过编写查询来建立查看统计信息的其他方式,这些查询使用与标准视图相同的底层统计访问函数。这些函数列于表 27.2中。每数据库访问函数以数据库 OID 为参数来标识要报告的数据库。每表和每索引函数以表或索引 OID 为参数。函数调用统计的函数以函数 OID 为参数。(注意,用这些函数只能看到当前数据库中的表、索引和函数。)每服务器进程访问函数以服务器进程编号为参数,其范围从 1 到当前活动服务器进程数。

表 27.2. 统计访问函数

Function Return Type Description
pg_stat_get_db_numbackends(oid) integer 数据库的活动服务器进程数
pg_stat_get_db_xact_commit(oid) bigint 数据库中已提交的事务数
pg_stat_get_db_xact_rollback(oid) bigint 数据库中已回滚的事务数
pg_stat_get_db_blocks_fetched(oid) bigint 数据库的磁盘块读取请求数
pg_stat_get_db_blocks_hit(oid) bigint 数据库在缓存中找到的磁盘块读取请求数
pg_stat_get_db_tuples_returned(oid) bigint 数据库返回的元组数
pg_stat_get_db_tuples_fetched(oid) bigint 数据库获取的元组数
pg_stat_get_db_tuples_inserted(oid) bigint 数据库中插入的元组数
pg_stat_get_db_tuples_updated(oid) bigint 数据库中更新的元组数
pg_stat_get_db_tuples_deleted(oid) bigint 数据库中删除的元组数
pg_stat_get_numscans(oid) bigint 参数为表时是完成的顺序扫描数,参数为索引时是完成的索引扫描数
pg_stat_get_tuples_returned(oid) bigint 参数为表时是顺序扫描读取的行数,参数为索引时是返回的索引条目数
pg_stat_get_tuples_fetched(oid) bigint 参数为表时是位图扫描取出的表行数,参数为索引时是使用该索引的简单索引扫描取出的表行数
pg_stat_get_tuples_inserted(oid) bigint 插入表中的行数
pg_stat_get_tuples_updated(oid) bigint 表中更新的行数(包括 HOT 更新)
pg_stat_get_tuples_deleted(oid) bigint 从表中删除的行数
pg_stat_get_tuples_hot_updated(oid) bigint Number of rows HOT-updated in table
pg_stat_get_live_tuples(oid) bigint 表中的活行数
pg_stat_get_dead_tuples(oid) bigint 表中的死行数
pg_stat_get_blocks_fetched(oid) bigint 表或索引的磁盘块读取请求数
pg_stat_get_blocks_hit(oid) bigint 表或索引在缓存中找到的磁盘块请求数
pg_stat_get_last_vacuum_time(oid) timestamptz 该表最近一次由用户发起的清理的时间
pg_stat_get_last_autovacuum_time(oid) timestamptz 该表最近一次由自动清理守护进程发起的清理的时间
pg_stat_get_last_analyze_time(oid) timestamptz 该表最近一次由用户发起的分析的时间
pg_stat_get_last_autoanalyze_time(oid) timestamptz 该表最近一次由自动清理守护进程发起的分析的时间
pg_backend_pid() integer 附属于当前会话的服务器进程的进程 ID
pg_stat_get_activity(integer) setof record 返回带有指定 PID 的后端的信息记录;如果指定NULL,则为系统中每个活动后端各返回一条记录。返回的字段是pg_stat_activity视图中字段的一个子集.
pg_stat_get_function_calls(oid) bigint 该函数被调用的次数
pg_stat_get_function_time(oid) bigint 花在该函数上的总挂钟时间,以微秒计。包括花在它调用的函数中的时间。
pg_stat_get_function_self_time(oid) bigint 仅花在该函数本身上的时间。不包括花在被调用函数中的时间。
pg_stat_get_backend_idset() setof integer 当前活动服务器进程编号的集合(从 1 到活动服务器进程数)。用法示例见正文。
pg_stat_get_backend_pid(integer) integer 给定服务器进程的进程 ID
pg_stat_get_backend_dbid(integer) oid 给定服务器进程的数据库 ID
pg_stat_get_backend_userid(integer) oid 给定服务器进程的用户 ID
pg_stat_get_backend_activity(integer) text 给定服务器进程的活动命令,但仅当当前用户是超级用户或与被查询会话的用户相同(且track_activities已启用)时可见
pg_stat_get_backend_waiting(integer) boolean 如果给定服务器进程正在等待锁则为真,但仅当当前用户是超级用户或与被查询会话的用户相同(且track_activities已启用)时可见
pg_stat_get_backend_activity_start(integer) timestamp with time zone 给定服务器进程当前执行的查询的启动时间,但仅当当前用户是超级用户或与被查询会话的用户相同(且track_activities已启用)时可见
pg_stat_get_backend_xact_start(integer) timestamp with time zone 给定服务器进程当前执行的事务的启动时间,但仅当当前用户是超级用户或与被查询会话的用户相同(且track_activities已启用)时可见
pg_stat_get_backend_start(integer) timestamp with time zone 给定服务器进程的启动时间;如果当前用户既不是超级用户也不是被查询会话的用户,则为 null
pg_stat_get_backend_client_addr(integer) inet 连接到给定服务器进程的客户端的 IP 地址;如果连接是通过 Unix 域套接字建立的,或者当前用户既不是超级用户也不是被查询会话的用户,则为 null
pg_stat_get_backend_client_port(integer) integer 连接到给定服务器进程的客户端的 TCP 端口号;如果连接是通过 Unix 域套接字建立的则为 -1;如果当前用户既不是超级用户也不是被查询会话的用户,则为 null
pg_stat_get_bgwriter_timed_checkpoints() bigint 后台写进程启动的定时检查点次数 (because the checkpoint_timeout time has expired)
pg_stat_get_bgwriter_requested_checkpoints() bigint 后台写进程因超出checkpoint_segments或因发出了CHECKPOINT命令而根据后端请求启动检查点的次数
pg_stat_get_bgwriter_buf_written_checkpoints() bigint 检查点期间后台写进程写出的缓冲区数
pg_stat_get_bgwriter_buf_written_clean() bigint 后台写进程为例行清理脏页而写出的缓冲区数
pg_stat_get_bgwriter_maxwritten_clean() bigint 后台写进程因写出的缓冲区数超过bgwriter_lru_maxpages参数指定值而中止其清理扫描的次数
pg_stat_get_buf_written_backend() bigint 后端因需要分配新缓冲区而写出的缓冲区数
pg_stat_get_buf_alloc() bigint 缓冲区分配总数
pg_stat_clear_snapshot() void 丢弃当前统计快照
pg_stat_reset() void 将当前数据库的所有统计计数器重置为零 (requires superuser privileges)
pg_stat_reset_shared(text) void 将数据库集簇的部分共享统计计数器重置为零(需要超级用户权限)。调用pg_stat_reset_shared('bgwriter')将把pg_stat_bgwriter显示的所有值清零。
pg_stat_reset_single_table_counters(oid) void 将当前数据库中单个表或索引的统计信息重置为零(需要超级用户权限)
pg_stat_reset_single_function_counters(oid) void 将当前数据库中单个函数的统计信息重置为零(需要超级用户权限)

注意

pg_stat_get_blocks_fetched减去pg_stat_get_blocks_hit得到的是为该表、索引或数据库发出的内核read()调用数;由于内核级缓冲,实际物理读取次数通常更低。*_blks_read统计列使用的就是这个差值,即 fetched 减 hit。

所有访问后端信息的函数都以 backend id 编号索引,唯一例外是以 PID 索引的pg_stat_get_activity。函数pg_stat_get_backend_idset提供了一种为每个活动服务器进程生成一行的便捷方法。例如,要显示所有服务器进程的PID和当前查询:

SELECT pg_stat_get_backend_pid(s.backendid) AS procpid,
       pg_stat_get_backend_activity(s.backendid) AS current_query
    FROM (SELECT pg_stat_get_backend_idset() AS backendid) AS s;

提交更正

译文有误、术语不当或页面显示问题,请到译文仓库 pgsty/pgdoc 报告译文问题。 英文原文本身的问题,请在当前版本的对应页面向上游反馈;上游不再修订已结束维护的版本。