PostgreSQL索引使用率分析


86

是否有工具或方法来分析Postgres,并确定应创建哪些缺少的索引,以及应删除哪些未使用的索引?我对SQLServer的“探查器”工具有一定的经验,但是我不知道Postgres附带的类似工具。


就是这样 好一阵子没看这个了。更新了我接受的答案。
塞林2015年

Answers:


164

我喜欢这样来查找丢失的索引:

SELECT
  relname                                               AS TableName,
  to_char(seq_scan, '999,999,999,999')                  AS TotalSeqScan,
  to_char(idx_scan, '999,999,999,999')                  AS TotalIndexScan,
  to_char(n_live_tup, '999,999,999,999')                AS TableRows,
  pg_size_pretty(pg_relation_size(relname :: regclass)) AS TableSize
FROM pg_stat_all_tables
WHERE schemaname = 'public'
      AND 50 * seq_scan > idx_scan -- more then 2%
      AND n_live_tup > 10000
      AND pg_relation_size(relname :: regclass) > 5000000
ORDER BY relname ASC;

这将检查是否有比索引扫描更多的序列扫描。如果表很小,它会被忽略,因为Postgres似乎更喜欢对它们进行顺序扫描。

上面的查询确实揭示了丢失的索引。

下一步将是检测缺少的组合索引。我想这并不容易,但可行。也许分析慢查询...我听说pg_stat_statements可以帮助...


15
要使用带引号的标识符将此查询更改为: SELECT relname, seq_scan-idx_scan AS too_much_seq, case when seq_scan-idx_scan>0 THEN 'Missing Index?' ELSE 'OK' END, pg_relation_size(relid::regclass) AS rel_size, seq_scan, idx_scan FROM pg_stat_all_tables WHERE schemaname='public' AND pg_relation_size(relid::regclass)>80000 ORDER BY too_much_seq DESC;
Muskrat先生,2016年

10
应该解释该查询的输出,以使答案更有用
cen

就@cen而言,当too_much_seq正数很大时,您应该关注。
mountainclimber11

1
@KishoreKumar我想postgres中的统计信息仍然包含在更新索引之前执行的查询。视您的流量而定,几个小时后统计信息将恢复正常。
guettli

1
::regclass不适用于大写标识符@Mr。Muskrat有一个很好的解决方案,也可以('"' || relname || '"')::regclass代替使用。
艾德里安


10

在确定丢失索引的方法上。但是,有一些计划使它在将来的发行版中变得更容易,例如伪索引和机器可读的EXPLAIN。

当前,您将需要EXPLAIN ANALYZE执行效果不佳的查询,然后手动确定最佳路线。一些日志分析器(例如pgFouine)可以帮助确定查询。

至于未使用的索引,可以使用以下类似内容来帮助识别它们:

select * from pg_stat_all_indexes where schemaname <> 'pg_catalog';

这将有助于识别已读取,已扫描,已获取的元组。


弗兰克·海肯斯(Frank Heikens)还指出了一些在其他地方查询当前索引使用情况的好地方。
rfusca 2010年

8

另一个用于分析PostgreSQL的有趣的新工具是PgHero。它更侧重于调整数据库,并进行了大量分析和建议。

屏幕截图


6

您可以在下面的查询中查找索引使用情况和索引大小:

参考来自此博客。

SELECT
    pt.tablename AS TableName
    ,t.indexname AS IndexName
    ,to_char(pc.reltuples, '999,999,999,999') AS TotalRows
    ,pg_size_pretty(pg_relation_size(quote_ident(pt.tablename)::text)) AS TableSize
    ,pg_size_pretty(pg_relation_size(quote_ident(t.indexrelname)::text)) AS IndexSize
    ,to_char(t.idx_scan, '999,999,999,999') AS TotalNumberOfScan
    ,to_char(t.idx_tup_read, '999,999,999,999') AS TotalTupleRead
    ,to_char(t.idx_tup_fetch, '999,999,999,999') AS TotalTupleFetched
FROM pg_tables AS pt
LEFT OUTER JOIN pg_class AS pc 
    ON pt.tablename=pc.relname
LEFT OUTER JOIN
( 
    SELECT 
        pc.relname AS TableName
        ,pc2.relname AS IndexName
        ,psai.idx_scan
        ,psai.idx_tup_read
        ,psai.idx_tup_fetch
        ,psai.indexrelname 
    FROM pg_index AS pi
    JOIN pg_class AS pc 
        ON pc.oid = pi.indrelid
    JOIN pg_class AS pc2 
        ON pc2.oid = pi.indexrelid
    JOIN pg_stat_all_indexes AS psai 
        ON pi.indexrelid = psai.indexrelid 
)AS T
    ON pt.tablename = T.TableName
WHERE pt.schemaname='public'
ORDER BY 1;

4

脚本有多个链接,可帮助您在PostgreSQL Wiki上找到未使用的索引。基本技术是查看pg_stat_user_indexes并查找其中idx_scan,该索引用于回答查询的次数为零或至少非常低。如果应用程序已更改,并且以前可能没有使用以前的索引,则有时您必须运行pg_stat_reset()以将所有统计信息恢复为0,然后收集新数据;您可以保存所有内容的当前值并计算一个增量,以解决此问题。

尚无任何好的工具可以建议缺少索引。一种方法是使用pgFouine或pqa等查询日志分析工具记录正在运行的查询,并分析哪些查询需要花费很长时间才能运行。有关更多信息,请参见“记录困难的查询”。

另一种方法是查看pg_stat_user_tables并查找对它们有大量顺序扫描的表,这些表seq_tup_fetch很大。使用索引时,idx_fetch_tup计数会增加。当一个表的索引编制得不够好,无法回答对该表的查询时,这可能会提示您。

实际弄清楚应该在哪些列上建立索引?这通常会再次导致查询日志分析。



1

对于PostgreSQL 9.4 +,PoWA似乎是一个有趣的工具。它收集统计数据,将其可视化并建议索引。它使用pg_stat_statements扩展名。

PoWA是PostgreSQL Workload Analyzer,它收集性能统计数据并提供实时图表,以帮助监视和调整PostgreSQL服务器。它类似于Oracle AWR或SQL Server MDW。


0
CREATE EXTENSION pgstattuple; 
CREATE TABLE test(t INT); 
INSERT INTO test VALUES(generate_series(1, 100000)); 
SELECT * FROM pgstatindex('test_idx'); 

version            | 2 
tree_level         | 2 
index_size         | 105332736 
root_block_no      | 412 
internal_pages     | 40 
leaf_pages         | 12804 
empty_pages        | 0 
deleted_pages      | 13 
avg_leaf_density   | 9.84 
leaf_fragmentation | 21.42 

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.