27.2. 统计收集器

PostgreSQL的统计收集器是一个支持收集和报告服务器活跃性信息的子系统。 目前,这个收集器可以给出对表和索引的访问计数, 包括磁盘块的数量和独立行的项。它还跟踪每个表中的行的总数, 每个表的过去的清理和分析时间。它也可以计算用户定义的函数的调用, 以及每个人的总花费的时间。

PostgreSQL还可以判断当前其它服务器进程正在执行的命令是什么。 这是一个收集过程中的独立设施。

27.2.1. 统计收集器配置

因为统计收集给查询处理增加了一些开销,所以该系统可以配置为启用或禁用统计收集。 这是由配置参数控制的,通常在postgresql.conf里设置 (参阅第 18 章获取有关设置配置参数的细节)。

参数track_activities启动监测任何服务器进程执行的当前命令。

参数track_counts控制关于表和索引是否被统计。

参数track_functions实现了对用户定义的函数用法的追踪。

参数track_io_timing启动监控块读写次数。

通常这些参数在postgresql.conf中设置,因此它们作用于所有服务器进程, 但是我们也可以在独立的会话里用SET命令把它们打开或者关闭。 为避免普通用户把它们的活跃性隐藏不给管理员看, 只有超级用户允许用SET命令修改这些参数。

统计收集器通过临时文件将采集到的信息传递给其他的PostgreSQL进程。 这些文件存放在stats_temp_directory参数命名的目录中。 缺省是pg_stat_tmp。 为了提高性能,stats_temp_directory参数可以指向一个基于RAM的文件系统, 降低物理I/O需求。当服务器关闭时, 统计数据的永久复本存储在global子目录中, 所以统计数据可以在服务器重新启动时保留。

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

有一些预定义的视图可以用于显示统计收集的结果, 在表 27-1里列出。 另外,我们可以使用底层的统计函数制作自定义的视图。 正如第 27.2.3 节中讨论的。

在使用统计观察当前活跃性的时候,你必须意识到这些信息并不是实时更新的。 每个独立的服务器进程只是在准备进入空闲状态的时候才向收集器传送新的块和行访问计数; 因此正在处理的查询或者事务并不影响显示出来的总数。同样, 收集器本身也最多每PGSTAT_STAT_INTERVAL毫秒 (缺省500,除非在编译服务器的时候修改过) 发送一次新的报告。因此显示总是落后于实际活动。 但是由track_activities收集的当前查询信息总是实时更新的。

另外一个需要着重指出的是,在请求服务器进程显示任何这些统计信息的时候, 它首先抓取收集器进程发出的最新报告,然后就拿这些数据作为所有统计视图和函数的快照, 直到它当前的事务结束。因此统计信息在当前事务的持续期间内显示静态信息。类似的, 每个进程的当前查询信息在该查询首次出现在事务中的时候就被收集了, 并且在整个事务过程中都显示相同的信息。这是一个特性,而不是一个Bug, 因为这样就允许你在统计上执行几个查询并且对结果进行相关性检查而又不用担心这些数字会悄悄的变化。 但是如果你想看每个查询的最新结果,那么就要记住在事务块外面处理这些查询。 另外,你可以调用pg_stat_clear_snapshot(), 这将丢弃目前事务的统计数据快照(如有)。 下次使用统计信息将导致获取一个新的快照。

在视图pg_stat_xact_all_tablespg_stat_xact_sys_tablespg_stat_xact_user_tablespg_stat_xact_user_functions上事务也可以看到自己的统计(未传送到收集器)。 这些数字不能作为上面所说的;相反他们在整个事务中不断更新。

表 27-1. 标准统计视图

视图名称描述
pg_stat_activity 每个服务器进程一行,显示进程当前活动相关的信息,比如状态和当前查询。 参阅pg_stat_activity获取更多详情。
pg_stat_bgwriter 只有一行,显示关于后端写进程活动的统计信息。参阅pg_stat_bgwriter 获取更多详细信息。
pg_stat_database 每个数据库一行,显示数据库广泛的统计。参阅pg_stat_database获取更多详情。
pg_stat_all_tables 当前数据库每个表一行,显示关于访问特定表的统计。参阅pg_stat_all_tables 获取更多详细信息。
pg_stat_sys_tablespg_stat_all_tables一样,除了只显示系统表之外。
pg_stat_user_tablespg_stat_all_tables一样,除了只显示用户表。
pg_stat_xact_all_tables类似pg_stat_all_tables, 但是到目前为止当前事务中计算采取的行动 (这包含在pg_stat_all_tables中以及相关视图中。) 活的列数以及死行和清理以及分析操作不在此视图中出现。
pg_stat_xact_sys_tablespg_stat_xact_all_tables相同,除了只显示系统表。
pg_stat_xact_user_tablespg_stat_xact_all_tables相同,除了只显示用户表。
pg_stat_all_indexes 当前数据库中的每个索引的每一行,显示关于访问特定索引的统计。 参见pg_stat_all_indexes获取更多详情。
pg_stat_sys_indexespg_stat_all_indexes一样,但只显示系统表上的索引。
pg_stat_user_indexespg_stat_all_indexes一样,但只显示用户表上的索引。
pg_statio_all_tables 当前数据库每个表一行,显示特定表关于I/O的统计, 参阅pg_statio_all_tables 获取更多细节。
pg_statio_sys_tablespg_statio_all_tables一样,但只显示系统表
pg_statio_user_tablespg_statio_all_tables一样,但只显示用户表。
pg_statio_all_indexes 当前数据库每个索引一行,显示特定索引关于I/O的统计。 参阅pg_statio_all_indexes获取更多细节。
pg_statio_sys_indexespg_statio_all_indexes一样的,但是只显示系统表上的索引。
pg_statio_user_indexespg_statio_all_indexes一样,但只显示用户表上的索引。
pg_statio_all_sequences 当前数据库每个序列一行,显示特定序列关于I/O的统计。参阅 pg_statio_all_sequences获取更多细节。
pg_statio_sys_sequencespg_statio_all_sequences一样, 但只显示系统序列。因为目前没有定义系统序列,所以这个视图总是空的。
pg_statio_user_sequencespg_statio_all_sequences一样,但只显示用户序列。
pg_stat_user_functions 每一个跟踪函数一行,显示关于执行这个函数的统计。 参阅pg_stat_user_functions 获取更多详情。
pg_stat_xact_user_functions 类似于pg_stat_user_functions,但是在当前事务中只调用计数 (这不包含在pg_stat_user_functions中)。
pg_stat_replication 每WAL发送进程一行,显示关于复制到发送端的链接备用服务器的统计信息。 参阅pg_stat_replication获取更多细节。
pg_stat_database_conflicts 每个数据库一行,显示关于备用服务器恢复冲突取消查询的统计信息。 参阅pg_stat_database_conflicts获取更多信息。

针对每个索引的统计有利于判断哪个索引得到使用以及它们的效果。

pg_statio_视图有利于决定缓冲区高速缓存的有效性。 当实际的磁盘数读取比缓冲区的数目小得多的时候, 然后缓存满足大多数读请求而没有调用内核调用。 然而,这些统计数据不提供整个过程:由于PostgreSQL 处理磁盘I/O的方式,不在PostgreSQL缓冲区缓存中的数据可能仍然位于 内核I/O缓存中,因此可能仍然被取出而不需要物理读。 对获得更多PostgreSQL的I/O行为的详细信息感兴趣的用户 建议使用与操作系统工具结合的PostgreSQL统计收集, 允许洞察I/O的内核处理。

表 27-2. pg_stat_activity视图

类型描述
datidoid连接后端的数据库OID
datnamename连接后端的数据库名称
pidinteger后端进程ID
usesysidoid登陆后端的用户OID
usenamename登陆到该后端的用户名
application_nametext连接到后端的应用名
client_addrinet连接到后端的客户端的IP地址。 如果此字段是null, 它表明通过服务器机器上UNIX套接字连接客户端或者这是内部进程如autovacuum
client_hostnametext连接客户端的主机名,通过client_addr的反向DNS查找报告。 这个字段将只是非空的IP连接,并且仅仅当启动log_hostname的时候。
client_portinteger客户端用于与后端通讯的TCP端口号,或者如果使用Unix套接字,则为-1
backend_starttimestamp with time zone该过程开始的时间,比如当客户端连接服务器时。
xact_starttimestamp with time zone启动当前事务的时间,如果没有事务是活的,则为null。如果当前查询是 首个事务,则这列等同于query_start列。
query_starttimestamp with time zone开始当前活跃查询的时间, 或者如果state是非活跃的, 当开始最后查询时。
state_changetimestamp with time zone上次状态改变的时间
waitingboolean如果后端当前正等待锁则为真
statetext 该后端当前总体状态。可能值是:

  • 活跃的:后端正在执行一个查询。

  • 空闲的:后端正在等待一个新的客户端命令。

  • 空闲事务:后端在事务中,但是目前无法执行查询。

  • 空闲事务(被终止):这个情况类似于空闲事务,除了事务导致错误的一个语句之一。

  • 快速路径函数调用:后端正在执行一个快速路径函数。

  • 禁用:如果后端禁用track_activities,则报告这个状态。

querytext该后端的最新查询文本。如果状态活跃的, 此字段显示当前正在执行的查询。在所有其他情况中,这表明执行过去的查询。

pg_stat_activity每个服务器进程有一行,显示进程当前活动的相关信息。

注意: waitingstate列是独立的。 如果一个后端处于活跃状态,它可能会或可能不会waiting。 如果这种情况是活跃的并且waiting是真, 它意味着正在执行一个查询,但在该系统中的某个地方被锁阻塞。

表 27-3. pg_stat_bgwriter视图

类型描述
checkpoints_timedbigint执行的定期检查点数
checkpoints_reqbigint执行的需求检查点数
checkpoint_write_timedouble precision 花费在检查点处理部分的时间总量,其中文件被写入到磁盘,以毫秒为单位。
checkpoint_sync_timedouble precision 花费在检查点处理部分的时间总量,其中文件被同步到磁盘,以毫秒为单位。
buffers_checkpointbigint检查点写缓冲区数量
buffers_cleanbigint后端写进程写缓冲区数量
maxwritten_cleanbigint后端写进程停止清理扫描时间数,因为它写了太多缓冲区
buffers_backendbigint通过后端直接写缓冲区数
buffers_backend_fsyncbigint 后端不得不执行自己的fsync调用的时间数 (通常后端写进程处理这些即使后端确实自己写)
buffers_allocbigint分配的缓冲区数量
stats_resettimestamp with time zone这些统计被重置的时间

pg_stat_bgwriter视图总是有独立行,包含集群的全局数据。

表 27-4. pg_stat_database视图

类型描述
datidoid数据库的OID
datnamename这个数据库的名字
numbackendsinteger当前连接到该数据库的后端数。 这是在返回一个反映目前状态值的视图中唯一的列;自 上次重置所有其他列返回累积值。
xact_commitbigint此数据库中已经提交的事务数
xact_rollbackbigint此数据库中已经回滚的事务数
blks_readbigint在这个数据库中读取的磁盘块的数量
blks_hitbigint高速缓存中已经发现的磁盘块的次数, 这样读取是不必要的(这只包括PostgreSQL缓冲区高速缓存,没有操作系统的文件系统缓存。
tup_returnedbigint通过数据库查询返回的行数
tup_fetchedbigint通过数据库查询抓取的行数
tup_insertedbigint通过数据库查询插入的行数
tup_updatedbigint通过数据库查询更新的行数
tup_deletedbigint通过数据库查询删除的行数
conflictsbigint由于数据库恢复冲突取消的查询数量。(只在备用服务器发生的冲突);参阅 pg_stat_database_conflicts获取更多信息。
temp_filesbigint 通过数据库查询创建的临时文件数量。计算所有临时文件, 不论为什么创建临时文件(比如排序或者哈希), 而且不管log_temp_files设置。
temp_bytesbigint通过数据库查询写入临时文件的数据总量。计算所有临时文件, 不论为什么创建临时文件, 而且不管log_temp_files设置
deadlocksbigint在该数据库中检索的死锁数
blk_read_timedouble precision通过数据库后端读取数据文件块花费的时间,以毫秒计算。
blk_write_timedouble precision通过数据库后端写入数据文件块花费的时间,以毫秒计算。
stats_resettimestamp with time zone这些统计最后被重置的时间

pg_stat_database视图将包含集群中每个数据库的每一行, 显示数据库统计。

表 27-5. pg_stat_all_tables视图

类型描述
relidoid表的OID
schemanamename此表的模式名
relnamename表名
seq_scanbigint此表发起的顺序扫描数
seq_tup_readbigint顺序扫描抓取的活跃行数
idx_scanbigint此表发起的索引扫描数
idx_tup_fetchbigint索引扫描抓取的活跃行数
n_tup_insbigint插入行数
n_tup_updbigint更新行数
n_tup_delbigint删除行数
n_tup_hot_updbigintHOT更新行数(比如没有更新所需的单独索引)
n_live_tupbigint估计活跃行数
n_dead_tupbigint估计死行数
last_vacuumtimestamp with time zone最后一次此表是手动清理的(不计算VACUUM FULL
last_autovacuumtimestamp with time zone上次被autovacuum守护进程清理的表
last_analyzetimestamp with time zone上次手动分析这个表
last_autoanalyzetimestamp with time zone上次被autovacuum守护进程分析的表
vacuum_countbigint这个表被手动清理的次数(不计算VACUUM FULL
autovacuum_countbigint这个表被autovacuum清理的次数
analyze_countbigint这个表被手动分析的次数
autoanalyze_countbigint这个表被autovacuum守护进程分析的次数

pg_stat_all_tables视图将包含 当前数据库中每个表的一行(包括TOAST表),显示访问特定表的统计信息。 pg_stat_user_tablespg_stat_sys_tables视图 包含相同的信息,但是过滤只分别显示用户和系统表。

表 27-6. pg_stat_all_indexes视图

类型描述
relidoid这个索引的表的OID
indexrelidoid索引的OID
schemanamename索引中模式名
relnamename索引的表名
indexrelnamename索引名
idx_scanbigint索引上开始的索引扫描数
idx_tup_readbigint通过索引上扫描返回的索引项数
idx_tup_fetchbigint通过使用索引的简单索引扫描抓取的活表行数

pg_stat_all_indexes视图将包含 当前数据库中的每个索引行,显示访问特定索引的统计。 pg_stat_user_indexespg_stat_sys_indexes视图包含相同的信息, 但是过滤只是分别显示用户和系统索引。

索引可以通过简单的索引扫描或"位图"索引扫描进行使用。位图扫描中 几个索引的输出可以通过AND或者OR规则进行组合, 因此当使用位图扫描的时候,很难将独立堆行抓取与特定索引进行组合, 因此,一个位图扫描增加pg_stat_all_indexes.idx_tup_read 使用索引计数,并且增加pg_stat_all_tables.idx_tup_fetch 表计数,但不影响pg_stat_all_indexes.idx_tup_fetch

注意: idx_tup_readidx_tup_fetch计算不同甚至没有任何可使用的位图扫描。 因为idx_tup_read计算从索引检索的索引项而idx_tup_fetch 计算从表抓取的活的行。如果任何死的或尚未提交的行使用索引进行抓取, 或通过唯一索引扫描避免任何堆抓取,则后者较小。

表 27-7. pg_statio_all_tables视图

类型描述
relidoid表OID
schemanamename该表模式名
relnamename表名
heap_blks_readbigint从该表中读取的磁盘块数
heap_blks_hitbigint此表缓存命中数
idx_blks_readbigint从表中所有索引读取的磁盘块数
idx_blks_hitbigint表中所有索引命中缓存数
toast_blks_readbigint此表的TOAST表读取的磁盘块数(如果存在)
toast_blks_hitbigint此表的TOAST表命中缓冲区数(如果存在)
tidx_blks_readbigint此表的TOAST表索引读取的磁盘块数(如果存在)
tidx_blks_hitbigint此表的TOAST表索引命中缓冲区数(如果存在)

pg_statio_all_tables视图将包含 当前数据库中每个表的一行(包括TOAST表), 显示出特定表I/O的统计。pg_statio_user_tablespg_statio_sys_tables视图包含相同的信息, 但是过滤分别只显示用户和系统表。

表 27-8. pg_statio_all_indexes视图

类型描述
relidoid索引的表的OID
indexrelidoid该索引的OID
schemanamename该索引的模式名
relnamename该索引的表名
indexrelnamename索引名称
idx_blks_readbigint从索引中读取的磁盘块数
idx_blks_hitbigint索引命中缓存数

pg_statio_all_indexes视图将包含当前数据库中的每个索引行, 显示特定索引的I/O的统计。pg_statio_user_indexespg_statio_sys_indexes视图包含相同的信息, 但是过滤分别只显示用户和系统索引。

表 27-9. pg_statio_all_sequences视图

类型描述
relidoid序列OID
schemanamename序列中模式名
relnamename序列名
blks_readbigint从序列中读取的磁盘块数
blks_hitbigint序列中缓存命中数

pg_statio_all_sequences视图包含当前数据库中每个序列的每一行, 显示特定序列关于I/O的统计。

表 27-10. pg_stat_user_functions视图

类型描述
funcidoid函数OID
schemanamename此函数中的模式名
funcnamename函数名
callsbigint被调用的函数次数
total_timedouble precision在这个函数以及调用的其他函数的总时间,以毫秒为单位。
self_timedouble precision在这个函数本身上用的总时间,不包含调用其他函数的,以毫秒为单位

pg_stat_user_functions视图包含每个跟踪函数的行,显示关于函数执行的统计。 track_functions参数控制真正跟踪的函数。

表 27-11. pg_stat_replication视图

类型描述
pidintegerWAL发送进程的ID
usesysidoid登陆到这个WAL发送进程的用户OID
usenamename登陆到WAL发送进程的用户名
application_nametext连接到这个WAL发送端的应用名
client_addrinet客户端连接到这个WAL发送端的IP地址,如果这个字段为null,它表明通过 服务器上Unix套接字连接客户端。
client_hostnametext连接客户端的主机名,通过client_addr的反向DNS查找报告。 并且当启用log_hostname时,这个字段对于IP连接是非空的。
client_portinteger客户端正在使用与WAL发送端连接的TCP端口号,或者如果使用Unix套接字则为-1
backend_starttimestamp with time zone这个进程开始时的时间,比如当客户端连接到这个WAL发送端时。
statetext当前WAL发送端状态
sent_locationtext在这次连接上发送的上次事务日志位置
write_locationtext通过备用服务器写入到磁盘的上次事务日志位置。
flush_locationtext通过备用服务器刷新到磁盘的上次事务日志位置。
replay_locationtext备用服务器上重播到数据库的上次事务日志位置。
sync_priorityinteger这个备用服务器被选为同步备用的优先级。
sync_statetext该备用服务器的同步状态

pg_stat_replication视图包含每个WAL发送进程的每一行, 显示发送端连接备用服务器有关复制的统计。列出只直接连接的备用; 没有可用的下游备用服务器的信息。

表 27-12. pg_stat_database_conflicts视图

类型描述
datidoid数据库的OID
datnamename数据库名称
confl_tablespacebigint由于删除的表空间,已经取消的数据库中的查询数量
confl_lockbigint由于锁超时,已经取消的数据库中的查询数
confl_snapshotbigint由于旧快照,已经取消的数据库查询数
confl_bufferpinbigint由于保留区而取消的数据库查询数
confl_deadlockbigint由于死锁已经被取消的数据库中的查询数

pg_stat_database_conflicts视图将包含 每个数据库的一行,显示由于备用服务器恢复发生的冲突而取消查询的数据库范围统计信息。 这种视图将只包含备用服务器的信息,因为在主服务器上不会发生冲突。

27.2.3. 统计函数

查看统计的其他方式可以通过写查询设置,它使用相同的底层统计访问功能用于 上面显示的标准视图。函数名称的详细信息,请参考标准的视图定义。(例如, 在psql中你可以发出\d+ pg_stat_activity。) 每个数据库统计的访问函数以数据库OID作为参数识别报告给数据库。 每个表和索引函数看成表或索引的OID。每个函数统计采取一个函数OID。 请注意,只有当前数据库中的表,索引,和函数可以看出这些功能。

统计收集相关的附加函数列在表 27-13中。

表 27-13. 附加统计函数

函数返回类型描述
pg_backend_pid()integer 服务器进程处理当前会话的进程ID
pg_stat_get_activity(integer)setof record 如果声明为NULL,则返回特定PID后端信息记录,或者系统中每个活动后端的记录。 返回的字段是pg_stat_activity视图中的子集。
pg_stat_clear_snapshot()void 丢弃当前数据库快照
pg_stat_reset()void 所有当前数据库统计计数器重置为零(需要超级用户权限)
pg_stat_reset_shared(text)void 重置一些集群范围统计计数为零,依赖于参数(需要超级用户权限)。 所有显示在pg_stat_bgwriter视图中的计数器调用pg_stat_reset_shared('bgwriter')将归零。
pg_stat_reset_single_table_counters(oid)void 为当前数据库中单一表或者索引重置统计为零(需要超级用户权限)
pg_stat_reset_single_function_counters(oid)void 当前数据库中单一功能重置统计为零(需要超级用户权限)

pg_stat_get_activitypg_stat_activity视图的基本功能返回 包含每个后端进程的所有可用信息的记录集。有时获取这些信息的子集更方便。 在这种情况下,可以使用每个后端统计访问函数的旧设置。这些都显示在 表 27-14中。这些访问函数使用后端ID号, 其范围从一到当前活动后端数。 函数pg_stat_get_backend_idset提供便利方式产生调用这些函数的每个活动后端的每一行。 比如,显示PID以及所有后端的当前查询:

SELECT pg_stat_get_backend_pid(s.backendid) AS pid,
       pg_stat_get_backend_activity(s.backendid) AS query
    FROM (SELECT pg_stat_get_backend_idset() AS backendid) AS s;

表 27-14. 每个后端统计函数

函数返回类型描述
pg_stat_get_backend_idset()setof integer设置当前活动的后端ID号(从1到活动后端数)
pg_stat_get_backend_activity(integer)text后端最近查询文本
pg_stat_get_backend_activity_start(integer)timestamp with time zone最近查询开始时间
pg_stat_get_backend_client_addr(integer)inet连接后端的客户端IP地址
pg_stat_get_backend_client_port(integer)integer客户端用于通讯的TCP端口号
pg_stat_get_backend_dbid(integer)oid连接后端的数据库OID
pg_stat_get_backend_pid(integer)integer后端进程ID
pg_stat_get_backend_start(integer)timestamp with time zone进程开始时间
pg_stat_get_backend_userid(integer)oid登陆到后端的用户OID
pg_stat_get_backend_waiting(integer)boolean如果后端正等待锁则为真
pg_stat_get_backend_xact_start(integer)timestamp with time zone当前事务的开始时间