PostgreSQL 的统计收集器是否跟踪*所有*索引的使用情况?

Does PostgreSQL's Statistics Collector track *all* usage of indexes?

在接管一个相当复杂的数据库的 DBA 职责后,我想消除任何占用大量磁盘 space 但未被使用的索引。我 运行 以下内容,以识别未使用的索引,排序以优先考虑那些在磁盘上消耗最多 space 的索引:

SELECT 
    schemaname,
    pg_stat_all_indexes.relname AS table,
    pg_class.relname AS index,
    pg_total_relation_size(oid) AS size,
    idx_scan,
    idx_tup_read,
    idx_tup_fetch
FROM  pg_class
JOIN pg_stat_all_indexes ON pg_stat_all_indexes.indexrelname = pg_class.relname
WHERE  
    relkind =('i')
ORDER BY size DESC

我有点惊讶有多少大索引似乎根本没有被使用——idx_scan 列的 0 就是证明。其中一些显然未使用的索引包括一个函数调用,它执行一些非常具体的事情(如下面的人为示例),并且似乎已设置为协助 API 功能。

--not real index
CREATE INDEX foo_transform_foo_name_idx
    ON foo USING btree
    (foo_transform_name(foo_name));

我的问题是统计收集器是否捕获了特定索引的所有 使用,即使这些索引是从 SQL 语言函数中扫描的,或者以其他方式?

这些索引从未被扫描过。但是,索引还有一些其他用途:

  • 它们强制执行唯一性和其他约束

  • 他们ANALYZE收集索引表达式的统计数据

使用来自 my blog 的查询来查找您可以删除而不会产生任何负面影响的索引:

SELECT s.schemaname,
       s.relname AS tablename,
       s.indexrelname AS indexname,
       pg_relation_size(s.indexrelid) AS index_size
FROM pg_catalog.pg_stat_user_indexes s
   JOIN pg_catalog.pg_index i ON s.indexrelid = i.indexrelid
WHERE s.idx_scan = 0      -- has never been scanned
  AND 0 <>ALL (i.indkey)  -- no index column is an expression
  AND NOT i.indisunique   -- is not a UNIQUE index
  AND NOT EXISTS          -- does not enforce a constraint
         (SELECT 1 FROM pg_catalog.pg_constraint c
          WHERE c.conindid = s.indexrelid)
ORDER BY pg_relation_size(s.indexrelid) DESC;