pgsql.cc 提供对 postgresql.org 官网内容的中文翻译,由 Pigsty 团队维护。
PostgreSQL的统计收集器是一个支持收集和报告服务器活动信息的子系统。 目前,对表和索引的访问分别以磁盘块和单行计数。每个表中的总行数, 以及每个表的清理和分析操作的信息也被计数。它还可以统计对用户定义函数的调用 和每个函数中花费的总时间。
PostgreSQL还支持报告其他服务器进程当前正在执行的确切命令。 此功能独立于收集器进程。
由于收集统计信息会增加查询执行的开销,因此可以配置系统是否收集信息。这由通常在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.1中,可用于显示统计信息收集的结果。也可以使用底层的统计函数构建自定义视图。
当使用统计信息来监视当前活动时,重要的是要意识到信息不会立即更新。每个单独的服务器进程会在转为空闲之前把新的统计计数发送给收集器,因此仍在进行中的查询或事务不会影响显示的总计。并且,收集器本身最多每隔PGSTAT_STAT_INTERVAL毫秒才会发出一份新报告一次(除非在构建服务器时做过修改,否则为 500)。因此,显示的信息会滞后于实际活动。然而,由track_activities收集的当前查询信息始终是最新的。
另一个重要点是,当要求服务器进程显示这些统计信息中的任何一种时,它会先取回收集器进程最近发出的报告,然后在当前事务结束之前,对所有统计视图和函数一直使用这一快照。因此,只要你继续当前事务,统计信息就会显示静态信息。类似地,在事务中第一次请求这类当前查询信息时,就会收集所有会话当前查询的信息,并且在整个事务期间显示的都是同一份信息。这是一个特性,而不是一个错误,因为它允许你对统计信息执行多个查询并对结果做关联,而不必担心数字在你眼前变化。但如果希望每个查询都看到新的结果,请确保在任何事务块之外执行这些查询。或者,也可以调用pg_stat_clear_snapshot(),它会丢弃当前事务的统计快照(如果有)。下一次使用统计信息时,就会获取一个新的快照。
A transaction can also see its own statistics (as yet untransmitted to the collector) in the views pg_stat_xact_all_tables, pg_stat_xact_sys_tables, pg_stat_xact_user_tables, and pg_stat_xact_user_functions中,或者通过这些视图的底层函数看到自己的统计信息(这些统计信息尚未传送给收集器)。这些数字不像上面所述那样起作用;相反,它们在事务期间持续更新。
表 27.1. 标准统计视图
| 视图名称 | Description |
|---|---|
pg_stat_activity |
每个服务器进程一行,显示数据库 OID、数据库名、进程 ID、用户 OID、用户名、应用名、客户端地址、主机名(如果可用)以及端口号、服务器进程、当前事务和当前查询开始执行的时间、进程的等待状态以及当前查询的文本。报告当前查询数据的列在参数track_activities被关闭时不可用。此外,只有查看视图的用户是超级用户或者与被报告进程的属主相同时,这些列才可见。客户端的主机名只有在设置了log_hostname或者在pg_hba.conf处理过程中需要查找用户的主机名时才可用。 |
pg_stat_bgwriter |
仅一行,显示来自后台写入器的集簇范围统计信息:已调度的检查点数量、被请求的检查点数量、由检查点和清理扫描写出的缓冲区,以及后台写入器因已写出过多缓冲区而停止清理扫描的次数。还包括有关共享缓冲池的统计信息,包括由后端(即非后台写入器)写出的缓冲区、这些后端不得不执行它们自己的 fsync 调用的次数(通常即使后端自己做写操作,后台写入器也会处理这些调用)、分配的总缓冲区数以及最近一次统计信息重置的时间。 |
pg_stat_database |
每个数据库一行,显示数据库 OID、数据库名、连接到该数据库的活动服务器进程数、在该数据库中提交和回滚的事务数、总磁盘块读取数、总缓冲区命中数(即因为块已在缓冲区缓存中被找到而避免的块读取请求数)、返回、抓取、插入、更新和删除的行数、因与恢复冲突(在备库上)而被取消的查询总数,以及最近一次统计信息重置的时间。 |
pg_stat_database_conflicts |
每个数据库一行,显示数据库 OID、数据库名以及该数据库中由于被删除的表空间、锁超时、旧快照、被固定的缓冲区和死锁而被取消的查询数。只在备库上包含信息,因为主库上不会发生冲突。 |
pg_stat_replication |
每个 WAL 发送进程一行,显示进程 ID、用户 OID、用户名、应用名、客户端地址、主机名(如果可用)和端口号、服务器进程开始执行的时间,以及当前 WAL 发送进程状态和事务日志位置。此外,备库会报告它收到并写入、刷出到磁盘以及重放的最近事务日志位置,这些信息也显示在这里。如果备库的应用名匹配synchronous_standby_names中的某一项设置,这里还会显示 sync_priority,即备库成为同步备库的顺序。详细说明连接具体在做什么的列只有当查看视图的用户是超级用户时才可见。客户端的主机名只有在设置了log_hostname或者在pg_hba.conf处理过程中需要查找用户的主机名时才可用。 |
pg_stat_all_tables |
对当前数据库中的每个表(包括 TOAST 表)显示表 OID、模式和表名、发起的顺序扫描数、由顺序扫描抓取的活行数、发起的索引扫描数(在该表所有索引上)、由索引扫描抓取的活行数、插入、更新和删除的行数、HOT 更新(即没有单独索引更新)的行数、活行和死行数、该表最近一次被手工非FULL清理的时间、最近一次被自动清理守护进程清理的时间、最近一次被手工分析的时间、最近一次被自动清理守护进程分析的时间、被手工非FULL清理的次数、被自动清理守护进程清理的次数、被手工分析的次数以及被自动清理守护进程分析的次数。 |
pg_stat_sys_tables |
和pg_stat_all_tables一样,但只显示系统表。 |
pg_stat_user_tables |
和pg_stat_all_tables一样,但只显示用户表。 |
pg_stat_xact_all_tables |
与 pg_stat_all_tables 相似,但只统计当前事务中截至目前执行的操作(这些操作尚未计入 pg_stat_all_tables 及相关视图)。此视图不包含存活行和死行数量以及清理、分析操作的列。 |
pg_stat_xact_sys_tables |
和pg_stat_xact_all_tables一样,但只显示系统表。 |
pg_stat_xact_user_tables |
和pg_stat_xact_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 |
和pg_statio_all_tables一样,但只显示系统表。 |
pg_statio_user_tables |
和pg_statio_all_tables一样,但只显示用户表。 |
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、模式、名称、调用次数、总时间和自身时间。自身时间是花在该函数本身的时间,总时间包括花在它调用的函数中的时间。时间值以毫秒计。 |
pg_stat_xact_user_functions |
和pg_stat_user_functions相似,但是只统计在当前事务期间的调用(还没有被包括在pg_stat_user_functions中)。 |
每个索引的统计信息对于判断哪些索引正在被使用以及它们有多有效尤其有用。
索引既可以被直接使用,也可以通过“位图扫描”使用。在位图扫描中,多个索引的输出可以通过 AND 或 OR 规则组合;因此当使用位图扫描时,很难把单个堆行抓取与特定的索引关联起来。 Therefore, a bitmap scan increments the pg_stat_all_indexes.idx_tup_read count(s) for the index(es) it uses, and it increments the pg_stat_all_tables.idx_tup_fetch count for the table, but it does not affect pg_stat_all_indexes.idx_tup_fetch.
在PostgreSQL 8.1 之前,idx_tup_read和idx_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. 统计访问函数
| 函数 | 返回类型 | Description |
|---|---|---|
|
integer |
数据库的活动服务器进程数 |
|
bigint |
数据库中已提交的事务数 |
|
bigint |
数据库中已回滚的事务数 |
|
bigint |
数据库的磁盘块读取请求数 |
|
bigint |
数据库在缓存中找到的磁盘块读取请求数 |
|
bigint |
数据库返回的元组数 |
|
bigint |
数据库获取的元组数 |
|
bigint |
数据库中插入的元组数 |
|
bigint |
数据库中更新的元组数 |
|
bigint |
数据库中删除的元组数 |
|
bigint |
由于与被删除表空间的恢复冲突而在数据库中被取消的查询数 |
|
bigint |
由于与锁的恢复冲突而在数据库中被取消的查询数 |
|
bigint |
由于与旧快照的恢复冲突而在数据库中被取消的查询数 |
|
bigint |
由于与被固定缓冲区的恢复冲突而在数据库中被取消的查询数 |
|
bigint |
由于与死锁的恢复冲突而在数据库中被取消的查询数 |
|
timestamptz |
该数据库最近一次统计信息重置的时间。在每个数据库第一次连接时初始化为系统时间。当在该数据库上调用pg_stat_reset以及对其中任意表或索引执行pg_stat_reset_single_table_counters时,重置时间会被更新。 |
|
bigint |
参数为表时是完成的顺序扫描数,参数为索引时是完成的索引扫描数 |
|
bigint |
参数为表时是顺序扫描读取的行数,参数为索引时是返回的索引条目数 |
|
bigint |
参数为表时是位图扫描取出的表行数,参数为索引时是使用该索引的简单索引扫描取出的表行数 |
|
bigint |
插入表中的行数 |
|
bigint |
表中更新的行数(包括 HOT 更新) |
|
bigint |
从表中删除的行数 |
|
bigint |
表中被 HOT 更新的行数 |
|
bigint |
表中的活行数 |
|
bigint |
表中的死行数 |
|
bigint |
表或索引的磁盘块读取请求数 |
|
bigint |
表或索引在缓存中找到的磁盘块请求数 |
|
timestamptz |
用户在此表上发起的最近一次非FULL清理的时间 |
|
timestamptz |
该表最近一次由自动清理守护进程发起的清理的时间 |
|
timestamptz |
该表最近一次由用户发起的分析的时间 |
|
timestamptz |
该表最近一次由自动清理守护进程发起的分析的时间 |
|
bigint |
此表被手工非FULL清理的次数 |
|
bigint |
此表被自动清理守护进程清理的次数 |
|
bigint |
此表被手工分析的次数 |
|
bigint |
此表被自动清理守护进程分析的次数 |
|
bigint |
在当前事务中,当参数是表时完成的顺序扫描数,或当参数是索引时完成的索引扫描数 |
|
bigint |
在当前事务中,当参数是表时由顺序扫描读取的行数,或当参数是索引时返回的索引项数 |
|
bigint |
在当前事务中,当参数是表时由位图扫描抓取的表行数,或当参数是索引时由使用该索引的简单索引扫描抓取的表行数 |
|
bigint |
在当前事务中插入表的行数 |
|
bigint |
在当前事务中更新的表行数(包括 HOT 更新) |
|
bigint |
在当前事务中从表删除的行数 |
|
bigint |
在当前事务中表中被 HOT 更新的行数 |
|
bigint |
在当前事务中为表或索引发出的磁盘块读取请求数 |
|
bigint |
在当前事务中在缓存中找到的表或索引磁盘块请求数 |
|
integer |
附属于当前会话的服务器进程的进程 ID |
|
setof record |
返回一条记录,包含指定 PID 的后端的信息;如果指定NULL,则为系统中的每个活动后端返回一条记录。返回字段是pg_stat_activity视图字段的子集。 |
|
bigint |
该函数被调用的次数 |
|
bigint |
花在该函数上的总挂钟时间,以微秒计。包括花在它调用的函数中的时间。 |
|
bigint |
仅花在该函数本身上的时间。不包括花在被调用函数中的时间。 |
|
bigint |
在当前事务中该函数被调用的次数。 |
|
bigint |
在当前事务中在该函数中花费的总挂钟时间,以微秒计。包括它调用的函数所花的时间。 |
|
bigint |
在当前事务中仅在此函数中花费的时间。被调用函数所花的时间被排除在外。 |
|
setof integer |
当前活动服务器进程编号的集合(从 1 到活动服务器进程数)。用法示例见正文。 |
|
integer |
给定服务器进程的进程 ID |
|
oid |
给定服务器进程的数据库 ID |
|
oid |
给定服务器进程的用户 ID |
|
text |
给定服务器进程的活动命令,但仅当当前用户是超级用户或与被查询会话的用户相同(且track_activities已启用)时可见 |
|
boolean |
如果给定服务器进程正在等待锁则为真,但仅当当前用户是超级用户或与被查询会话的用户相同(且track_activities已启用)时可见 |
|
timestamp with time zone |
给定服务器进程当前执行的查询的启动时间,但仅当当前用户是超级用户或与被查询会话的用户相同(且track_activities已启用)时可见 |
|
timestamp with time zone |
给定服务器进程当前执行的事务的启动时间,但仅当当前用户是超级用户或与被查询会话的用户相同(且track_activities已启用)时可见 |
|
timestamp with time zone |
给定服务器进程的启动时间;如果当前用户既不是超级用户也不是被查询会话的用户,则为 null |
|
inet |
连接到给定服务器进程的客户端的 IP 地址;如果连接是通过 Unix 域套接字建立的,或者当前用户既不是超级用户也不是被查询会话的用户,则为 null |
|
integer |
连接到给定服务器进程的客户端的 TCP 端口号;如果连接是通过 Unix 域套接字建立的则为 -1;如果当前用户既不是超级用户也不是被查询会话的用户,则为 null |
|
bigint |
后台写进程启动的定时检查点次数 (because the checkpoint_timeout time has expired) |
|
bigint |
后台写进程因超出checkpoint_segments或因发出了CHECKPOINT命令而根据后端请求启动检查点的次数 |
|
bigint |
检查点期间后台写进程写出的缓冲区数 |
|
bigint |
后台写进程为例行清理脏页而写出的缓冲区数 |
|
bigint |
后台写进程因写出的缓冲区数超过bgwriter_lru_maxpages参数指定值而中止其清理扫描的次数 |
|
timestamptz |
后台写入器最近一次统计信息重置的时间,在数据库集簇上执行pg_stat_reset_shared('bgwriter')时更新。 |
|
bigint |
后端因需要分配新缓冲区而写出的缓冲区数 |
|
bigint |
缓冲区分配总数 |
|
setof record |
每个活动 wal 发送进程一条记录。返回的字段是pg_stat_replication视图字段的一个子集。 |
|
void |
丢弃当前统计信息快照 |
|
void |
将当前数据库的所有统计计数器重置为零(需要超级用户权限) |
|
void |
将数据库集簇的部分共享统计计数器重置为零(需要超级用户权限)。调用pg_stat_reset_shared('bgwriter')将把pg_stat_bgwriter显示的所有值清零。 |
|
void |
将当前数据库中单个表或索引的统计信息重置为零(需要超级用户权限) |
|
void |
将当前数据库中单个函数的统计信息重置为零(需要超级用户权限) |
pg_stat_get_blocks_fetched减去pg_stat_get_blocks_hit得到为该表、索引或数据库发出的内核read()调用次数;由于内核级的缓冲,实际物理读取的次数通常更低。*_blks_read统计列使用这个减法,即取出的减去命中的。
所有访问后端信息的函数都以 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 报告译文问题。 英文原文本身的问题,请在当前版本的对应页面向上游反馈;上游不再修订已结束维护的版本。