Postgresを分析し、どの欠落インデックスを作成し、どの未使用インデックスを削除するかを決定するためのツールまたは方法はありますか?SQLServerの「プロファイラー」ツールでこれを行った経験は少しありますが、Postgresに含まれている同様のツールを知りません。
回答:
私はこれが不足しているインデックスを見つけるのが好きです:
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が役立つと聞きました...
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;
too_much_seq
ば、が正で大きい場合は心配する必要があります。
::regclass
大文字の識別子@Mrでは機能しません。マスクラットには良い解決策がありますが、('"' || relname || '"')::regclass
代わりに使用することも可能です。
統計を確認してください。pg_stat_user_tables
とpg_stat_user_indexes
は、最初のものです。
「統計コレクター」を参照してください。
欠落しているインデックスの決定アプローチについて....いいえ。ただし、疑似インデックスや機械可読EXPLAINなど、将来のリリースでこれを簡単にする計画がいくつかあります。
現在、EXPLAIN ANALYZE
クエリのパフォーマンスを低下させてから、最適なルートを手動で決定する必要があります。pgFouineなどの一部のログアナライザーは、クエリの判別に役立ちます。
未使用のインデックスに関しては、次のようなものを使用してそれらを識別できます。
select * from pg_stat_all_indexes where schemaname <> 'pg_catalog';
これは、読み取られ、スキャンされ、フェッチされたタプルを識別するのに役立ちます。
以下のクエリを使用して、インデックスの使用状況とインデックスのサイズを見つけることができます。
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;
PostgreSQLwikiで未使用のインデックスを見つけるのに役立つスクリプトへの複数のリンクがあります。基本的な手法は、そのインデックスがクエリへの回答に使用された回数のカウントがゼロであるか、少なくとも非常に少ないpg_stat_user_indexes
ものを探して探すidx_scan
ことです。アプリケーションが変更され、以前に使用されていたインデックスが現在ではない可能性がある場合は、実行pg_stat_reset()
してすべての統計を0に戻し、新しいデータを収集する必要がある場合があります。すべての現在の値を保存し、代わりにデルタを計算してそれを把握することができます。
不足しているインデックスを提案するために利用できる優れたツールはまだありません。1つのアプローチは、実行中のクエリをログに記録し、pgFouineやpqaなどのクエリログ分析ツールを使用して、実行に時間がかかるクエリを分析することです。詳細については、「難しいクエリのログ記録」を参照してください。
もう1つのアプローチはpg_stat_user_tables
、テーブルに対して多数の順次スキャンが行われているテーブルを調べて探すことですseq_tup_fetch
。インデックスを使用すると、idx_fetch_tup
代わりにカウントが増加します。これは、テーブルがそれに対するクエリに答えるのに十分なインデックスが付けられていない場合にあなたを手がかりにすることができます。
次に、どの列にインデックスを付ける必要があるかを実際に把握していますか?これは通常、クエリログ分析に戻ります。
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
PoWAは、PostgreSQL9.4以降の興味深いツールのようです。統計を収集して視覚化し、インデックスを提案します。pg_stat_statements
拡張子を使用します。
PoWAは、パフォーマンス統計を収集し、PostgreSQLサーバーの監視と調整に役立つリアルタイムのチャートとグラフを提供するPostgreSQLワークロードアナライザーです。これは、OracleAWRまたはSQLServerMDWに似ています。
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