【问题标题】:PostgreSQL Index Usage AnalysisPostgreSQL 索引使用分析
【发布时间】:2011-03-20 02:58:36
【问题描述】:

是否有工具或方法可以分析 Postgres,并确定应该创建哪些缺失的索引,以及应该删除哪些未使用的索引?我对使用 SQLServer 的“分析器”工具执行此操作有一点经验,但我不知道 Postgres 中包含类似的工具。

【问题讨论】:

    标签: sql database-design postgresql


    【解决方案1】:

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

    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 than 2%
          AND n_live_tup > 10000
          AND pg_relation_size(relname :: regclass) > 5000000
    ORDER BY relname ASC;
    

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

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

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

    【讨论】:

    • 要使用带引号的标识符,请将查询更改为: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;
    • 就@cen 而言,当too_much_seq 是积极的并且很大时,您应该关注。
    • 我在其中一个表上创建了几个索引,但这个查询仍然显示了该表上缺少的索引。
    • @KishoreKumar 我猜 postgres 中的统计信息仍然包含在您更新索引之前执行的查询。根据您的流量,统计数据会在几个小时后再次恢复正常。
    • ::regclass 不适用于大写标识符,@Mr。麝鼠有一个很好的解决方案,也可以用('"' || relname || '"')::regclass代替。
    【解决方案2】:

    检查统计数据。 pg_stat_user_tablespg_stat_user_indexes 是开始的。

    见“The Statistics Collector”。

    【讨论】:

      【解决方案3】:

      关于确定缺失索引的方法....不。但是有一些计划在未来的版本中让这更容易,比如伪索引和机器可读的解释。

      目前,您需要EXPLAIN ANALYZE 性能不佳的查询,然后手动确定最佳路线。像pgFouine 这样的一些日志分析器可以帮助确定查询。

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

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

      这将有助于识别读取、扫描、提取的元组。

      【讨论】:

        【解决方案4】:

        另一个用于分析 PostgreSQL 的有趣的新工具是 PgHero。它更专注于调优数据库,并提出大量的分析和建议。

        【讨论】:

          【解决方案5】:

          您可以使用以下查询来查找索引使用情况和索引大小:

          Reference is taken from this blog.

          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;
          

          【讨论】:

            【解决方案6】:

            可以在 postgres 控制台中使用以下查询找到

            use db_name
            select * from pg_stat_user_indexes;
            select * from pg_statio_user_indexes;
            

            更多详情https://www.postgresql.org/docs/current/monitoring-stats.html

            【讨论】:

              【解决方案7】:

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

              目前还没有任何好的工具可以建议缺失的索引。一种方法是记录您正在运行的查询,并使用 pgFouine 或 pqa 等查询日志分析工具分析哪些查询需要很长时间才能运行。有关详细信息,请参阅“Logging Difficult Queries”。

              另一种方法是查看pg_stat_user_tables 并查找对它们进行大量顺序扫描的表,其中seq_tup_fetch 很大。当使用索引时,idx_fetch_tup 计数会增加。这可以提示您何时一个表的索引不够好,无法回答针对它的查询。

              实际上确定了您应该在哪些列上建立索引?这通常会再次导致查询日志分析的内容。

              【讨论】:

                【解决方案8】:

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

                PoWA 是 PostgreSQL 工作负载分析器,可收集性能统计数据并提供实时图表和图形,以帮助监控和调整您的 PostgreSQL 服务器。它类似于 Oracle AWR 或 SQL Server MDW。

                【讨论】:

                  【解决方案9】:
                  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 
                  

                  【讨论】:

                    猜你喜欢
                    • 2014-11-19
                    • 1970-01-01
                    • 2021-12-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 2017-06-30
                    • 1970-01-01
                    相关资源
                    最近更新 更多