受支持版本: 当前版本 (18) / 17 / 16 / 15 / 14
开发版本: devel

F.24. pg_buffercache #

pg_buffercache 模块提供了一种手段,可实时检查共享缓冲区缓存中正在发生的情况。 它还提供了一种底层方式,可出于测试目的从中逐出数据。

该模块提供 pg_buffercache_pages() 函数(由 pg_buffercache 视图封装)、 pg_buffercache_numa_pages() 函数(由 pg_buffercache_numa 视图封装)、 pg_buffercache_summary() 函数、 pg_buffercache_usage_counts() 函数、 pg_buffercache_evict() 函数、 pg_buffercache_evict_relation() 函数以及 pg_buffercache_evict_all() 函数。

pg_buffercache_pages() 函数返回一组记录, 每一行描述一个共享缓冲区条目的状态。为便于使用, pg_buffercache 视图封装了该函数。

pg_buffercache_numa_pages() 函数提供共享缓冲区条目的 NUMA 节点映射。这部分信息并不属于 pg_buffercache_pages() 本身,因为检索它要慢得多。为便于使用, pg_buffercache_numa 视图封装了该函数。

pg_buffercache_summary() 函数返回一行, 汇总共享缓冲区缓存的状态。

pg_buffercache_usage_counts() 函数返回一组记录, 每行描述具有给定使用计数的缓冲区数量。

默认情况下,上述函数仅限超级用户以及拥有 pg_monitor 角色权限的角色使用。可以使用 GRANT 将访问权限授予其他角色。

pg_buffercache_evict() 函数允许根据给定的缓冲区标识符, 从缓冲池中逐出一个块。该函数仅限超级用户使用。

pg_buffercache_evict_relation() 函数允许根据给定的关系标识符, 从缓冲池中逐出该关系中所有未钉住的共享缓冲区。该函数仅限 超级用户使用。

pg_buffercache_evict_all() 函数允许 从缓冲池中逐出所有未钉住的共享缓冲区。该函数仅限超级用户使用。

F.24.1. pg_buffercache 视图 #

该视图公开的列定义见 Table F.14

Table F.14. pg_buffercache

列类型

描述

bufferid integer

ID,范围为 1..shared_buffers

relfilenode oid (references pg_class.relfilenode)

关系的 filenode 编号

reltablespace oid (references pg_tablespace.oid)

关系的表空间 OID

reldatabase oid (references pg_database.oid)

关系的数据库 OID

relforknumber smallint

关系中的分支编号;见 common/relpath.h

relblocknumber bigint

关系中的页号

isdirty boolean

该页是否为脏页?

usagecount smallint

时钟扫描访问计数

pinning_backends integer

钉住该缓冲区的后端数量


共享缓存中的每个缓冲区都有一行记录。未使用的缓冲区除了 bufferid 之外,其余字段均显示为 null。共享系统目录显示为属于数据库 0。

由于缓存由所有数据库共享,其中通常会有不属于当前数据库的关系页。 这意味着某些行在 pg_class 中可能没有可匹配的行, 甚至还可能出现错误的连接结果。如果要与 pg_class 进行连接, 最好将连接限制在 reldatabase 等于当前数据库 OID 或 0 的那些行上。

由于复制该视图将要显示的缓冲区状态数据时不会获取缓冲区管理器锁, 访问 pg_buffercache 视图对正常缓冲区活动的影响较小, 但它不会为所有缓冲区提供一致的结果集。不过,我们会确保每个缓冲区的信息本身是一致的。

F.24.2. pg_buffercache_numa 视图 #

该视图公开的列定义见 Table F.15

Table F.15. pg_buffercache_numa

列类型

描述

bufferid integer

ID,范围为 1..shared_buffers

os_page_num bigint

该缓冲区对应的操作系统内存页号

numa_node int

NUMA 节点 ID


由于为每个页查询 NUMA 节点 ID 需要先访问并调入相应的内存页, 首次执行该函数可能需要明显的时间。无论是否首次执行,获取这些信息的代价都很高, 因此不建议高频查询该视图。

Warning

在确定 NUMA 节点时,该视图会访问共享内存段中的所有内存页。 如果共享内存尚未分配,这会强制完成分配,并且这些内存可能会被分配到单个 NUMA 节点上(取决于系统配置)。

F.24.3. pg_buffercache_summary() 函数 #

该函数公开的列定义见 Table F.16

Table F.16. pg_buffercache_summary() 输出列

列类型

描述

buffers_used int4

已使用的共享缓冲区数量

buffers_unused int4

未使用的共享缓冲区数量

buffers_dirty int4

脏共享缓冲区的数量

buffers_pinned int4

被钉住的共享缓冲区数量

usagecount_avg float8

已使用共享缓冲区的平均使用计数


pg_buffercache_summary() 函数返回一行, 汇总所有共享缓冲区的状态。类似且更详细的信息由 pg_buffercache 视图提供,但 pg_buffercache_summary() 的开销显著更低。

pg_buffercache 视图一样, pg_buffercache_summary() 不获取缓冲区管理器锁。 因此,并发活动可能导致结果存在轻微误差。

F.24.4. pg_buffercache_usage_counts() 函数 #

该函数公开的列定义见 Table F.17

Table F.17. pg_buffercache_usage_counts() 输出列

列类型

描述

usage_count int4

一种可能的缓冲区使用计数值

buffers int4

具有该使用计数的缓冲区数量

dirty int4

具有该使用计数的脏缓冲区数量

pinned int4

具有该使用计数的已钉住缓冲区数量


pg_buffercache_usage_counts() 函数返回一组行, 按可能的使用计数值聚合后汇总所有共享缓冲区的状态。类似且更详细的信息 由 pg_buffercache 视图提供,但 pg_buffercache_usage_counts() 的开销显著更低。

pg_buffercache 视图一样, pg_buffercache_usage_counts() 不获取缓冲区管理器锁。 因此,并发活动可能导致结果存在轻微误差。

F.24.5. pg_buffercache_evict() 函数 #

pg_buffercache_evict() 函数接受一个缓冲区标识符, 如 pg_buffercache 视图中的 bufferid 列所示。它返回该缓冲区是否被逐出以及是否被刷出的信息。 buffer_evicted 列在成功时为 true;如果缓冲区无效、因被钉住而无法逐出, 或者在尝试将其写出后再次变脏,则为 false。buffer_flushed 列在缓冲区被刷出时为 true。 这并不一定表示该缓冲区是由我们刷出的,也可能是由其他人刷出的。 由于并发活动,该结果在返回时就可能已经过时,因为该缓冲区随时都可能再次变为有效。 该函数仅供开发人员测试。

F.24.6. pg_buffercache_evict_relation() 函数 #

pg_buffercache_evict_relation() 函数与 pg_buffercache_evict() 函数非常相似。不同之处在于, pg_buffercache_evict_relation() 接受的是关系标识符, 而不是缓冲区标识符。它会尝试逐出该关系所有分支中的全部缓冲区。 它返回被逐出的缓冲区数、被刷出的缓冲区数以及无法逐出的缓冲区数。 被刷出的缓冲区不一定是由我们刷出的,也可能是由其他人刷出的。由于并发活动, 缓冲区可能会立刻再次被读入,因此该结果在返回时就可能已经过时。该函数仅供开发人员测试。

F.24.7. pg_buffercache_evict_all() 函数 #

pg_buffercache_evict_all() 函数与 pg_buffercache_evict() 函数非常相似。不同之处在于, pg_buffercache_evict_all() 不接收参数; 它会尝试逐出缓冲池中的所有缓冲区。它返回被逐出的缓冲区数、被刷出的缓冲区数 以及无法逐出的缓冲区数。被刷出的缓冲区不一定是由我们刷出的,也可能是由其他人刷出的。 由于并发活动,缓冲区可能会立刻再次被读入,因此该结果在返回时就可能已经过时。 该函数仅供开发人员测试。

F.24.8. 示例输出 #

regression=# SELECT n.nspname, c.relname, count(*) AS buffers
             FROM pg_buffercache b JOIN pg_class c
             ON b.relfilenode = pg_relation_filenode(c.oid) AND
                b.reldatabase IN (0, (SELECT oid FROM pg_database
                                      WHERE datname = current_database()))
             JOIN pg_namespace n ON n.oid = c.relnamespace
             GROUP BY n.nspname, c.relname
             ORDER BY 3 DESC
             LIMIT 10;

  nspname   |        relname         | buffers
------------+------------------------+---------
 public     | delete_test_table      |     593
 public     | delete_test_table_pkey |     494
 pg_catalog | pg_attribute           |     472
 public     | quad_poly_tbl          |     353
 public     | tenk2                  |     349
 public     | tenk1                  |     349
 public     | gin_test_idx           |     306
 pg_catalog | pg_largeobject         |     206
 public     | gin_test_tbl           |     188
 public     | spgist_text_tbl        |     182
(10 rows)


regression=# SELECT * FROM pg_buffercache_summary();
 buffers_used | buffers_unused | buffers_dirty | buffers_pinned | usagecount_avg
--------------+----------------+---------------+----------------+----------------
          248 |        2096904 |            39 |              0 |       3.141129
(1 row)


regression=# SELECT * FROM pg_buffercache_usage_counts();
 usage_count | buffers | dirty | pinned
-------------+---------+-------+--------
           0 |   14650 |     0 |      0
           1 |    1436 |   671 |      0
           2 |     102 |    88 |      0
           3 |      23 |    21 |      0
           4 |       9 |     7 |      0
           5 |     164 |   106 |      0
(6 rows)

F.24.9. 作者 #

Mark Kirkwood

设计建议:Neil Conway

调试建议:Tom Lane

提交更正

如果您发现文档中有不正确的内容、与您使用特定功能的经验不符或需要进一步说明,请使用此表单来报告文档问题。