PgSQL中pg_stat_user_tables 和 pg_stat_user_objects参数详解

pg_stat_user_tablespg_stat_user_objects 是PostgreSQL 中两个 非常重要的性能监控和统计视图。

核心概念

这两个视图都属于 PostgreSQL 的**统计收集器(Statistics Collector)**子系统。它们提供了关于数据库对象使用情况和性能的宝贵信息,是进行数据库性能分析、瓶颈排查和SQL调优的基石。

要确保这些视图中有数据,必须先确认 track_counts 参数是 on 的(默认通常是开启的)。

sql 复制代码
SHOW track_counts;

1. pg_stat_user_tables

这个视图专门用于收集和显示当前数据库中用户定义表的统计信息。每个用户表对应一行记录。

主要字段详解

这些字段通常从最后一次重置统计信息(使用 pg_stat_reset())或者数据库启动开始累积。

字段名 类型 描述
relid OID 表的对象标识符(OID)
schemaname name 表所在的模式名(如 public
relname name 表的名字
seq_scan bigint 在此表上发起的顺序扫描(全表扫描)的次数
seq_tup_read bigint 顺序扫描读取的活元组(行)数(可能包含已删除但未清理的行
idx_scan bigint 在此表上所有索引的索引扫描总次数
idx_tup_fetch bigint 通过索引扫描读取的活元组数
n_tup_ins bigint 插入的行数
n_tup_upd bigint 更新的行数(包含HOT更新和不HOT更新)
n_tup_del bigint 删除的行数
n_tup_hot_upd bigint HOT(仅堆元组)更新的行数。HOT更新是一种优化,避免更新索引。
n_live_tup bigint 表中当前估算的活元组数(是估算值,非精确值
n_dead_tup bigint 表中当前估算的死元组数(是估算值,是VACUUM的主要目标
n_mod_since_analyze bigint 自上次分析(ANALYZE)以来插入、更新或删除的估算行数
last_vacuum timestamp 最后一次手动或自动VACUUM此表的时间
last_autovacuum timestamp 最后一次autovacuum守护进程清理此表的时间
last_analyze timestamp 最后一次手动ANALYZE此表的时间
last_autoanalyze timestamp 最后一次autoanalyze守护进程分析此表的时间
vacuum_count bigint 此表被手动VACUUM的次数
autovacuum_count bigint 此表被autovacuum进程清理的次数
analyze_count bigint 此表被手动ANALYZE的次数
autoanalyze_count bigint 此表被autoanalyze进程分析的次数
经典使用场景和查询示例
  1. 识别全表扫描过多的表

    顺序扫描成本很高,特别是对大表。如果一个表频繁被全表扫描,应考虑为查询条件添加索引。

    sql 复制代码
    SELECT schemaname, relname, seq_scan, seq_tup_read,
           seq_tup_read / NULLIF(seq_scan, 0) AS avg_tuples_per_scan
    FROM pg_stat_user_tables
    WHERE seq_scan > 0
    ORDER BY seq_tup_read DESC
    LIMIT 10;
  2. 评估索引使用情况

    检查哪些表"读多写少"但索引使用率却很低,这些表可能是添加索引的候选。

    sql 复制代码
    SELECT schemaname, relname, seq_scan, idx_scan,
           n_tup_ins, n_tup_upd, n_tup_del,
           CASE WHEN (seq_scan + idx_scan) > 0
                THEN (idx_scan * 100.0) / (seq_scan + idx_scan)
                ELSE 0
           END AS idx_scan_pct
    FROM pg_stat_user_tables
    ORDER BY n_tup_ins + n_tup_upd + n_tup_del DESC; -- 按写入量排序

    如果 idx_scan_pct 很低,但表读取量(seq_tup_read)很高,说明查询可能没走索引。

  3. 监控死元组和自动清理状态

    死元组过多会导致表膨胀、查询性能下降。这是监控autovacuum工作的核心视图。

sql 复制代码
SELECT schemaname, relname,
       n_live_tup, n_dead_tup,
       (n_dead_tup * 100.0 / NULLIF((n_live_tup + n_dead_tup), 0)) AS dead_tup_ratio,
       last_autovacuum, last_autoanalyze
FROM pg_stat_user_tables
ORDER BY n_dead_tup DESC
LIMIT 10;
python 复制代码
注:此SQL用了NULLIF函数,这是最简洁和高效避免报错ERROR:division by zero的方法:
- 在除数为零时返回 NULL
- 避免了除零错误
- 代码简洁易读
- NULLIF() 函数会在 (n_live_tup + n_dead_tup) 为零时返回 NULL,而任何数除以 NULL 都会返回 NULL,从而避免错误。

SQL报错解决方案链接:https://blog.csdn.net/liumangtuzi888/article/details/151362257?sharetype=blogdetail\&sharerId=151362257\&sharerefer=PC\&sharesource=liumangtuzi888\&spm=1011.2480.3001.8118

如果 dead_tup_ratio 过高且 last_autovacuum 是很久以前,可能需要调查autovacuum为何没有正常工作。

  1. 查看表的数据变更频率

    sql 复制代码
    SELECT schemaname, relname,
           n_tup_ins AS inserts,
           n_tup_upd AS updates,
           n_tup_del AS deletes,
           (n_tup_ins + n_tup_upd + n_tup_del) AS total_changes
    FROM pg_stat_user_tables
    ORDER BY total_changes DESC
    LIMIT 10;

2. pg_stat_user_objects

有些PostgreSQL 版本不支持此视图

这个视图提供了更上层、更概括的统计信息,它涵盖了所有用户定义的对象(表、索引、序列、视图、物化视图等),但每个对象只有一行非常基础的统计信息。

主要字段详解
字段名 类型 描述
relid OID 对象的对象标识符(OID)
schemaname name 对象所在的模式名
relname name 对象的名字
relkind char 对象类型标识r = 普通表 i = 索引 S = 序列 v = 视图 m = 物化视图 c = 组合类型 t = TOAST表 f = 外表
relpages bigint 磁盘上表示该关系的页数(尺寸的近似值,基于last vacuumanalyze
reltuples bigfloat 表中的行数(尺寸的近似值,基于last vacuumanalyze

注意pg_stat_user_objects 没有 seq_scan, n_tup_ins 等详细的I/O或DML统计信息。那些信息在更专门的视图里(如 pg_stat_user_tables, pg_statio_user_indexes)。

经典使用场景和查询示例
  1. 获取数据库中所有用户对象的大小估算

    这是一个快速查看对象大小和行数的概览方法。

    sql 复制代码
    SELECT schemaname,
           relname,
           CASE relkind
               WHEN 'r' THEN 'ordinary table'
               WHEN 'i' THEN 'index'
               WHEN 'S' THEN 'sequence'
               WHEN 'v' THEN 'view'
               WHEN 'm' THEN 'materialized view'
               ELSE 'other'
           END AS object_type,
           pg_size_pretty(pg_relation_size(relid)) AS size, -- 更精确的大小
           reltuples::bigint AS estimated_rows
    FROM pg_stat_user_objects
    ORDER BY pg_relation_size(relid) DESC;
  2. 查找最大的表和索引

    sql 复制代码
    SELECT schemaname, relname,
           CASE WHEN relkind = 'i' THEN 'INDEX' ELSE 'TABLE' END AS type,
           pg_size_pretty(pg_relation_size(relid)) AS size
    FROM pg_stat_user_objects
    WHERE relkind IN ('r', 'i') -- 只查表和索引
    ORDER BY pg_relation_size(relid) DESC
    LIMIT 20;

核心区别与联系

特性 pg_stat_user_tables pg_stat_user_objects
范围 仅限用户表 所有用户对象(表、索引、序列、视图等)
统计粒度 非常详细:包含扫描、读写、元组、 vacuum 等 非常基础:主要是对象类型和大小估算
主要用途 性能调优:查询分析、索引优化、Vacuum监控 对象管理:尺寸监控、对象清单浏览
关系 它是 pg_stat_user_objects 的一个子集和详细补充 它是所有用户对象的一个概览目录

重置统计信息

你可以使用以下函数重置统计信息(通常需要超级用户权限)。谨慎操作,因为这会使历史趋势数据丢失。

python 复制代码
-- 重置当前数据库的所有统计信息
SELECT pg_stat_reset();

-- 重置单个表的统计信息
SELECT pg_stat_reset_single_table_counters(<table_oid>);
SELECT pg_stat_reset_single_function_counters(<function_oid>);

总结

  • 当你需要深入分析表的访问模式、I/O性能、DML操作和Vacuum状态 时,使用 pg_stat_user_tables。这是DBA进行日常性能诊断最常用的视图之一。
  • 当你需要快速查看数据库中有哪些对象、它们的类型和大致大小 时,使用 pg_stat_user_objects 。它更像一个增强版的 pg_class 视图,附带了一些统计信息。

通常,你会从 pg_stat_user_objects 找到一个感兴趣的大对象,然后通过它的 relidrelkind 去更专门的统计视图(如 pg_stat_user_tablespg_statio_user_indexes)中获取其详细性能数据。

相关推荐
黑马金牌编程1 小时前
深入浅出 Redis:从核心原理到运维实战指南一
数据库·redis·缓存·性能优化·非关系型数据库
李迟1 小时前
2025年9月个人工作生活总结
服务器·数据库·生活
大聪明-PLUS2 小时前
通过 Telnet 实现自动化
linux·嵌入式·arm·smarc
Lin_Aries_04212 小时前
容器化 Tomcat 应用程序
java·linux·运维·docker·容器·tomcat
吃不胖没烦恼2 小时前
Alibaba Cloud Linux 3 +Docker 部署 ThinkPHP6 (宝塔环境)-问题篇
运维·docker·容器
HAORChain2 小时前
Fabric 2.x 外部链码部署(External Chaincode Service)实战攻略
linux·docker·区块链·fabric
Lin_Aries_04212 小时前
部署 GitLab 服务器
linux·运维·服务器·docker·gitlab·github
appdeveloperxg3 小时前
Centos 7 创建ftp 匿名登录和专用用户名登录可上传下载
linux·服务器
野犬寒鸦3 小时前
从零起步学习Redis || 第四章:Cache Aside Pattern(旁路缓存模式)以及优化策略
java·数据库·redis·后端·spring·缓存
停走的风3 小时前
关于Pycharm的conda虚拟环境包更改路径问题的配置问题
linux·pycharm·conda