You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PostgreSQL统计采集器是否会统计所有索引的使用情况?

核心结论

PostgreSQL 的统计收集器会捕获所有索引扫描记录,不管索引是在顶层SQL中调用、SQL/PLPGSQL函数内部调用,还是表达式索引(也就是你提到的含函数调用的索引)被匹配使用,都会正常累加idx_scan计数,没有遗漏。


你观测到大量索引idx_scan=0的常见原因

  1. 索引识别查询存在逻辑漏洞
    你当前的查询仅通过indexrelname关联pg_class和pg_stat_all_indexes,如果不同schema、不同表存在同名索引,关联结果会错乱,非常容易把实际有扫描的索引错判为0扫描。
    正确的关联逻辑应该通过唯一的索引OID关联,修正后的查询如下:
SELECT 
    s.schemaname,
    s.relname AS table_name,
    c.relname AS index_name,
    pg_size_pretty(pg_total_relation_size(c.oid)) AS size, -- 直接转成可读大小更方便
    s.idx_scan,
    s.idx_tup_read,
    s.idx_tup_fetch
FROM pg_class c
JOIN pg_stat_all_indexes s ON s.indexrelid = c.oid
WHERE c.relkind = 'i'
ORDER BY pg_total_relation_size(c.oid) DESC;
  1. 统计数据周期不足
    pg_stat_all_indexes的计数会在以下场景清零:
  • PostgreSQL实例重启
  • 手动执行了pg_stat_reset()或pg_stat_reset_shared('bgwriter')等统计重置命令
    如果统计数据的累计周期没有覆盖完整的业务周期(比如没包含月末结算、定时任务等低频业务场景),就会出现低频使用的索引被误判为未使用的情况。
    你可以通过SELECT pg_postmaster_start_time();查询实例启动时间,确认统计周期是否足够。
  1. 表达式索引从未被优化器匹配
    你提到的含函数调用的索引属于表达式索引,只有当查询中的过滤/排序条件和索引定义的表达式完全一致,且函数不可变性符合要求时,优化器才会选择走该索引。如果业务SQL从来没有写出能匹配该索引的条件,那索引确实从未被使用,idx_scan自然为0。

  2. 索引仅用于约束校验,从未被查询扫描
    idx_scan仅统计查询执行时主动扫描索引的次数,索引的维护操作(插入/更新/删除时修改索引内容、唯一约束校验等)不会被计入该字段。如果一个索引是唯一约束、主键约束对应的索引,且从来没有查询使用过它做过滤/排序,也会出现idx_scan=0的情况。


安全清理未使用索引的建议

如果是PostgreSQL 12及以上版本,对拿不准的索引可以先设置为不可见:

ALTER INDEX 索引名 SET (invisible = on);

不可见索引会被优化器忽略,但依然会在数据写入时正常维护,观察1~2个完整业务周期,确认没有性能下降、业务报错后再执行删除操作,出现问题可以随时执行ALTER INDEX 索引名 SET (invisible = off);恢复。


内容的提问来源于stack exchange,提问作者M. Andersen

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.26 10:06:04