PostgreSQL 中文参考文档
🌐 英文原版 官方 ↗

F.25. pg_buffercache — 检查 PostgreSQL 缓冲区缓存状态 #

F.25.1. pg_buffercache 视图
F.25.2. pg_buffercache_numa 视图
F.25.3. pg_buffercache_summary() 函数
F.25.4. pg_buffercache_usage_counts() 函数
F.25.5. pg_buffercache_evict() 函数
F.25.6. pg_buffercache_evict_relation() 函数
F.25.7. pg_buffercache_evict_all() 函数
F.25.8. 输出示例
F.25.9. 作者

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.25.1. pg_buffercache 视图 #

视图暴露的列定义见 Table F.14。

Table F.14. pg_buffercache 列

列类型

描述

bufferid integer

ID,取值范围 1..shared_buffers

relfilenode oid (引用 pg_class.relfilenode)

关系的 filenode 编号

reltablespace oid (引用 pg_tablespace.oid)

关系的表空间 OID

reldatabase oid (引用 pg_database.oid)

关系的数据库 OID

relforknumber smallint

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

relblocknumber bigint

关系内的页码

isdirty boolean

页面是否为脏?

usagecount smallint

时钟扫描访问计数

pinning_backends integer

固定该缓冲区的后端数量


共享缓存中的每个缓冲区各占一行。未使用的缓冲区除 bufferid 外所有字段均为空。共享系统目录显示为属于数据库零。

由于缓存被所有数据库共享,通常会有不属于当前数据库的关系的页面。这意味着某些行在 pg_class 中可能没有匹配的连接行,甚至可能产生错误的连接。如果你要连接 pg_class,最好把连接限制在 reldatabase 等于当前数据库 OID 或零的行上。

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

F.25.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.25.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.25.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.25.5. pg_buffercache_evict() 函数 #

pg_buffercache_evict() 函数接受一个缓冲区标识符,即 pg_buffercache 视图 bufferid 列所示。它返回缓冲区是否被逐出并刷写的信息。buffer_evicted 列在成功时为真;在缓冲区无效、因被固定而无法逐出,或在尝试写出后再次变脏时为假。buffer_flushed 列在缓冲区被刷写时为真。这不一定意味着缓冲区是由我们刷写的,也可能是其他人刷写的。返回后结果立即过时,因为由于并发活动,缓冲区随时可能重新变为有效。该函数仅供开发者测试使用。

F.25.6. pg_buffercache_evict_relation() 函数 #

pg_buffercache_evict_relation() 函数与 pg_buffercache_evict() 函数非常相似。区别在于 pg_buffercache_evict_relation() 接受关系标识符而非缓冲区标识符。它会尝试逐出该关系所有分支的所有缓冲区。 它返回被逐出的缓冲区数、被刷写的缓冲区数以及无法逐出的缓冲区数。被刷写的缓冲区不一定是由我们刷写的,也可能是其他人刷写的。返回后结果立即过时,因为由于并发活动,缓冲区可能立即被读回。该函数仅供开发者测试使用。

F.25.7. pg_buffercache_evict_all() 函数 #

pg_buffercache_evict_all() 函数与 pg_buffercache_evict() 函数非常相似。区别在于 pg_buffercache_evict_all() 函数不接收参数;它会尝试逐出缓冲池中的所有缓冲区。它返回被逐出的缓冲区数、被刷写的缓冲区数以及无法逐出的缓冲区数。被刷写的缓冲区不一定是由我们刷写的,也可能是其他人刷写的。返回后结果立即过时,因为由于并发活动,缓冲区可能立即被读回。该函数仅供开发者测试使用。

F.25.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.25.9. 作者 #

Mark Kirkwood

设计建议:Neil Conway

调试建议:Tom Lane