pgstattuple 模块提供多个获取元组级统计信息的函数。
由于这些函数返回详细的页面级信息,访问默认受到限制。默认情况下,只有角色 pg_stat_scan_tables 拥有 EXECUTE 权限。超级用户自然不受该限制。扩展安装后,用户可以执行 GRANT 命令更改这些函数的权限,允许其他人执行。不过,更好的做法可能是把这些用户加入 pg_stat_scan_tables 角色。
pgstattuple(regclass) returns record
pgstattuple 返回关系的物理长度、“死亡”元组的百分比以及其他信息。这可以帮助用户判断是否需要清理。参数是目标关系的名称(可选带模式限定)或 OID。例如:
test=> SELECT * FROM pgstattuple('pg_catalog.pg_proc');
-[ RECORD 1 ]------+-------
table_len | 458752
tuple_count | 1470
tuple_len | 438896
tuple_percent | 95.67
dead_tuple_count | 11
dead_tuple_len | 3157
dead_tuple_percent | 0.69
free_space | 8932
free_percent | 1.95
输出列见 Table F.24。
Table F.24. pgstattuple 输出列
| 列 | 类型 | 描述 |
|---|---|---|
table_len | bigint | 关系的物理长度(字节) |
tuple_count | bigint | 存活元组的数量 |
tuple_len | bigint | 存活元组的总长度(字节) |
tuple_percent | float8 | 存活元组的百分比 |
dead_tuple_count | bigint | 死亡元组的数量 |
dead_tuple_len | bigint | 死亡元组的总长度(字节) |
dead_tuple_percent | float8 | 死亡元组的百分比 |
free_space | bigint | 空闲空间总量(字节) |
free_percent | float8 | 空闲空间的百分比 |
table_len 总是大于 tuple_len、dead_tuple_len 与 free_space 之和。差值来自固定的页面开销、每页指向元组的指针表,以及为保证元组正确对齐而进行的填充。
pgstattuple 只在关系上获取读锁。因此结果不反映瞬时快照;并发更新会影响它们。
如果 HeapTupleSatisfiesDirty 返回假,pgstattuple 就判定元组为“死亡”。
pgstattuple(text) returns record
与 pgstattuple(regclass) 相同,只是目标关系以 TEXT 形式指定。保留该函数是为了向后兼容,并将在未来的某个版本中弃用。
pgstatindex(regclass) returns record
pgstatindex 返回一条记录,显示关于 B 树索引的信息。例如:
test=> SELECT * FROM pgstatindex('pg_cast_oid_index');
-[ RECORD 1 ]------+------
version | 2
tree_level | 0
index_size | 16384
root_block_no | 1
internal_pages | 0
leaf_pages | 1
empty_pages | 0
deleted_pages | 0
avg_leaf_density | 54.27
leaf_fragmentation | 0
输出列为:
| 列 | 类型 | 描述 |
|---|---|---|
version | integer | B 树版本号 |
tree_level | integer | 根页面的树层级 |
index_size | bigint | 索引总大小(字节) |
root_block_no | bigint | 根页面的位置(没有则为零) |
internal_pages | bigint | “内部”(上层)页面的数量 |
leaf_pages | bigint | 叶子页面的数量 |
empty_pages | bigint | 空页面的数量 |
deleted_pages | bigint | 已删除页面的数量 |
avg_leaf_density | float8 | 叶子页面的平均密度 |
leaf_fragmentation | float8 | 叶子页面碎片化程度 |
报告的 index_size 通常比 internal_pages + leaf_pages +
empty_pages + deleted_pages 所对应的页面多一页,因为它还包含索引的元页面。
与 pgstattuple 一样,结果是逐页累加的,不应期望它代表整个索引的瞬时快照。
pgstatindex(text) returns record
与 pgstatindex(regclass) 相同,只是目标索引以 TEXT 形式指定。保留该函数是为了向后兼容,并将在未来的某个版本中弃用。
pgstatginindex(regclass) returns record
pgstatginindex 返回一条记录,显示关于 GIN 索引的信息。例如:
test=> SELECT * FROM pgstatginindex('test_gin_index');
-[ RECORD 1 ]--+--
version | 1
pending_pages | 0
pending_tuples | 0
输出列为:
| 列 | 类型 | 描述 |
|---|---|---|
version | integer | GIN 版本号 |
pending_pages | integer | 待处理列表中的页面数 |
pending_tuples | bigint | 待处理列表中的元组数 |
pgstathashindex(regclass) returns record
pgstathashindex 返回一条记录,显示关于 HASH 索引的信息。例如:
test=> select * from pgstathashindex('con_hash_index');
-[ RECORD 1 ]--+-----------------
version | 4
bucket_pages | 33081
overflow_pages | 0
bitmap_pages | 1
unused_pages | 32455
live_items | 10204006
dead_items | 0
free_percent | 61.8005949100872
输出列为:
| 列 | 类型 | 描述 |
|---|---|---|
version | integer | HASH 版本号 |
bucket_pages | bigint | 桶页面的数量 |
overflow_pages | bigint | 溢出页面的数量 |
bitmap_pages | bigint | 位图页面的数量 |
unused_pages | bigint | 未使用页面的数量 |
live_items | bigint | 存活元组的数量 |
dead_tuples | bigint | 死亡元组的数量 |
free_percent | float | 空闲空间的百分比 |
pg_relpages(regclass) returns bigint
pg_relpages 返回关系中的页面数。
pg_relpages(text) returns bigint
与 pg_relpages(regclass) 相同,只是目标关系以 TEXT 形式指定。保留该函数是为了向后兼容,并将在未来的某个版本中弃用。
pgstattuple_approx(regclass) returns record
pgstattuple_approx 是 pgstattuple 的更快替代,返回近似结果。参数是目标关系的名称或 OID。例如:
test=> SELECT * FROM pgstattuple_approx('pg_catalog.pg_proc'::regclass);
-[ RECORD 1 ]--------+-------
table_len | 573440
scanned_percent | 2
approx_tuple_count | 2740
approx_tuple_len | 561210
approx_tuple_percent | 97.87
dead_tuple_count | 0
dead_tuple_len | 0
dead_tuple_percent | 0
approx_free_space | 11996
approx_free_percent | 2.09
输出列见 Table F.25。
pgstattuple 总是执行全表扫描,返回存活与死亡元组(及其大小)和空闲空间的精确计数,而 pgstattuple_approx 尽量避免全表扫描,返回精确的死亡元组统计,以及存活元组数量、大小和空闲空间的近似值。
它通过跳过可见性映射中标记为只有可见元组的页面来实现这一点(如果页面设置了对应的 VM 位,则假定它不包含死亡元组)。对于这类页面,它从空闲空间映射获取空闲空间值,并假定页面上其余空间被存活元组占用。
对于无法跳过的页面,它会扫描每个元组,把其存在与大小记入相应的计数器,并累加页面上的空闲空间。最后,它根据扫描到的页面数与元组数估算存活元组的总数(方式与 VACUUM 估算 pg_class.reltuples 相同)。
Table F.25. pgstattuple_approx 输出列
| 列 | 类型 | 描述 |
|---|---|---|
table_len | bigint | 关系的物理长度(字节)(精确) |
scanned_percent | float8 | 表被扫描的百分比 |
approx_tuple_count | bigint | 存活元组的数量(估算) |
approx_tuple_len | bigint | 存活元组的总长度(字节)(估算) |
approx_tuple_percent | float8 | 存活元组的百分比 |
dead_tuple_count | bigint | 死亡元组的数量(精确) |
dead_tuple_len | bigint | 死亡元组的总长度(字节)(精确) |
dead_tuple_percent | float8 | 死亡元组的百分比 |
approx_free_space | bigint | 空闲空间总量(字节)(估算) |
approx_free_percent | float8 | 空闲空间的百分比 |
在上面的输出中,空闲空间的数值与 pgstattuple 的输出可能不完全一致,因为空闲空间映射给出的数字是精确的,但不保证精确到字节。
Tatsuo Ishii, Satoshi Nagayasu 和 Abhijit Menon-Sen