SELECT
schemaname AS 模式名,
relname AS 表名,
n_tup_ins AS 新增行数,
last_autoanalyze AS 上次自动分析时间
FROM pg_stat_user_tables
-- 筛选近30天有数据改动
WHERE last_analyze >= NOW() - INTERVAL '30 days'
-- 过滤系统表,只查业务表
AND schemaname NOT IN ('pg_catalog', 'information_schema')
ORDER BY schemaname,last_analyze DESC;
sql
SELECT
schemaname AS 模式名,
relname AS 表名,
n_tup_ins AS 新增行数,
last_autoanalyze AS 上次自动分析时间
FROM pg_stat_user_tables
-- 筛选近30天有数据改动
WHERE last_analyze >= NOW() - INTERVAL '30 days'
-- 过滤系统表,只查业务表
AND schemaname NOT IN ('pg_catalog', 'information_schema')
ORDER BY schemaname,last_analyze DESC;
整条 SQL 完整作用拆解(PostgreSQL 专属语句)
一、整体功能
查询近 30 天被手动执行过分析(analyze)的所有业务数据表,展示归属模式、表名、历史新增总行数、上次自动分析的时间,先按模式分组,同模式下按上次分析时间由新到旧排序。
区分两个关键字段:
last_analyze:手动 / 主动执行 ANALYZE 命令 的最后时间(WHERE 过滤条件用的是这个)last_autoanalyze:数据库后台 autovacuum 进程自动触发分析的最后时间(仅展示,不作为筛选)
二、逐段拆解
1. FROM pg_stat_user_tables
pg_stat_user_tables 是 PG 内置系统统计视图,专门存放普通用户业务表的运行统计信息,不含系统内置表,核心可获取:表增删改行数、分析、真空、访问频次、扫描行数等运行指标。
2. SELECT 字段释义
表格
| 字段 | 别名 | 含义 |
|---|---|---|
| schemaname | 模式名 | 表所属 schema(对应 MySQL 的数据库库名),业务库一般是 public、自定义业务 schema |
| relname | 表名 | 数据表真实名称 |
| n_tup_ins | 新增行数 | 数据库启动至今,该表累计INSERT 插入的总行数(不含 update、delete),是累计统计值,不是近 30 天新增 |
| last_autoanalyze | 上次自动分析时间 | PG 自动清理进程自动执行 analyze 的时间,自动分析用于更新表统计信息、优化器生成合理执行计划 |
3. WHERE 过滤条件
-
last_analyze >= NOW() - INTERVAL '30 days'只保留近 30 天人为手动执行过 ANALYZE 的表; 很多时候 DBA 会手动执行 ANALYZE 修复统计信息失真、解决索引不走、SQL 变慢问题,这条语句可以统计近期做过统计刷新的表。 ⚠️ 注意:自动分析不会更新last_analyze,只会更新last_autoanalyze。 -
schemaname NOT IN ('pg_catalog', 'information_schema')排除 PG 自带系统元数据表,只查询我们自己创建的业务数据表,避免一堆系统元数据干扰结果。
4. ORDER BY schemaname,last_analyze DESC
- 优先按 schema 名称正序排列;
- 同一个模式内,最近执行手动 ANALYZE 的表排在最上方。
三、使用场景
- 运维排查:统计近期哪些表被人工刷新过统计信息,复盘慢 SQL 优化操作记录;
- 巡检核对:对比手动 analyze 时间和系统自动分析时间,判断自动真空进程是否工作正常;
- 业务数据表盘点:结合累计插入行数,查看近期维护过的表的数据写入体量。
四、这条 SQL 存在的小缺陷 & 优化建议
- 筛选逻辑容易产生误解 WHERE 用
last_analyze过滤(手动分析),展示列却是last_autoanalyze(自动分析),两字段无绑定关系,容易看混数据; n_tup_ins是数据库服务重启后的累计值,不是近 30 天新增数据,无法反映近期写入量;- 若业务从来没人手动执行 ANALYZE,整张查询结果会是空数据。
简易优化参考(按需选用)
sql
SELECT
schemaname AS 模式名,
relname AS 表名,
n_tup_ins AS 累计新增行数,
last_analyze AS 上次手动分析时间,
last_autoanalyze AS 上次自动分析时间
FROM pg_stat_user_tables
WHERE (last_analyze >= NOW() - INTERVAL '30 days' OR last_autoanalyze >= NOW() - INTERVAL '30 days')
AND schemaname NOT IN ('pg_catalog', 'information_schema')
ORDER BY schemaname, COALESCE(last_analyze, last_autoanalyze) DESC;