Analyse de l'utilisation des index PostgreSQL

87

Existe-t-il un outil ou une méthode pour analyser Postgres et déterminer quels index manquants doivent être créés et quels index inutilisés doivent être supprimés? J'ai une petite expérience en faisant cela avec l'outil "profiler" pour SQLServer, mais je ne connais pas un outil similaire inclus avec Postgres.

Cerin
la source
Donc c'est. Je n'ai pas regardé cela depuis un moment. J'ai mis à jour ma réponse acceptée.
Cerin

Réponses:

164

J'aime ceci pour trouver les index manquants:

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;

Cela vérifie s'il y a plus de balayages de séquence que de balayages d'index. Si la table est petite, elle est ignorée, car Postgres semble préférer les scans séquentiels pour eux.

La requête ci-dessus révèle des index manquants.

La prochaine étape serait de détecter les index combinés manquants. Je suppose que ce n'est pas facile, mais faisable. Peut-être analyser les requêtes lentes ... J'ai entendu dire que pg_stat_statements pourrait aider ...

guettli
la source
15
Pour que cela fonctionne avec les identifiants cités, changez la requête en: 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;
M. Muskrat
10
La sortie de cette requête doit être expliquée pour rendre la réponse plus utile
cen
Pour le point de @cen, quand too_much_seqest positif et grand, vous devriez vous inquiéter.
mountainclimber11
1
@KishoreKumar Je suppose que les statistiques dans postgres contiennent toujours les requêtes qui ont été exécutées avant la mise à jour de votre index. En fonction de votre trafic, les statistiques seront à nouveau correctes après quelques heures.
guettli
1
::regclassne fonctionnera pas sur les identifiants en majuscules, @Mr. Le rat musqué a une bonne solution, il est également possible de l'utiliser à la ('"' || relname || '"')::regclassplace.
Adrien
21

Vérifiez les statistiques. pg_stat_user_tableset ce pg_stat_user_indexessont eux pour commencer.

Voir « Le collecteur de statistiques ».

Frank Heikens
la source
10

Sur l'approche de déterminer les index manquants ... Non. Mais il y a des plans pour rendre cela plus facile dans les prochaines versions, comme les pseudo-index et EXPLAIN lisible par machine.

Actuellement, vous aurez besoin de EXPLAIN ANALYZErequêtes peu performantes, puis de déterminer manuellement le meilleur itinéraire. Certains analyseurs de journaux comme pgFouine peuvent aider à déterminer les requêtes.

En ce qui concerne les index inutilisés, vous pouvez utiliser quelque chose comme ce qui suit pour les identifier:

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

Cela aidera à identifier les tuples lus, scannés, récupérés.

rfusca
la source
Frank Heikens signale également quelques bons endroits d'autres endroits pour interroger sur l'utilisation actuelle des index.
rfusca
8

Un autre outil nouveau et intéressant pour analyser PostgreSQL est PgHero . Il se concentre davantage sur le réglage de la base de données et fait de nombreuses analyses et suggestions.

capture d'écran

n1000
la source
6

Vous pouvez utiliser la requête ci-dessous pour trouver l'utilisation de l'index et la taille de l'index:

La référence est tirée de ce 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;
Anvesh
la source
4

Il existe plusieurs liens vers des scripts qui vous aideront à trouver des index inutilisés sur le wiki PostgreSQL . La technique de base consiste à regarder pg_stat_user_indexeset à rechercher ceux où idx_scan, le nombre de fois où cet index a été utilisé pour répondre à des requêtes, est égal à zéro ou au moins très faible. Si l'application a changé et qu'un index autrefois utilisé ne l'est probablement pas, vous devez parfois exécuter pg_stat_reset()pour ramener toutes les statistiques à 0 et collecter de nouvelles données; vous pouvez enregistrer les valeurs actuelles pour tout et calculer un delta à la place pour le comprendre.

Il n'y a pas encore de bons outils disponibles pour suggérer des index manquants. Une approche consiste à consigner les requêtes que vous exécutez et à analyser celles qui prennent beaucoup de temps à s'exécuter à l'aide d'un outil d'analyse du journal des requêtes comme pgFouine ou pqa. Voir « Journalisation des requêtes difficiles » pour plus d'informations.

L'autre approche consiste à rechercher pg_stat_user_tableset à rechercher des tables qui comportent un grand nombre d'analyses séquentielles par rapport à elles, où seq_tup_fetchest grand. Lorsqu'un index est utilisé, le idx_fetch_tupnombre est augmenté à la place. Cela peut vous indiquer quand une table n'est pas suffisamment indexée pour répondre aux requêtes qui la concernent.

En fait, déterminer sur quelles colonnes vous devez ensuite indexer? Cela revient généralement à l'analyse du journal des requêtes.

Greg Smith
la source
1

PoWA semble être un outil intéressant pour PostgreSQL 9.4+. Il recueille des statistiques, les visualise et propose des index. Il utilise l' pg_stat_statementsextension.

PoWA est un analyseur de charge de travail PostgreSQL qui rassemble des statistiques de performances et fournit des graphiques en temps réel pour aider à surveiller et à régler vos serveurs PostgreSQL. Il est similaire à Oracle AWR ou SQL Server MDW.

n1000
la source
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 
madjardi
la source
-1

Cela devrait aider: Analyse pratique des requêtes

João Pereira
la source
1
La dernière mise à jour de PQA date de plusieurs années. A-t-il une fonctionnalité qui n'est pas prise en charge par pgFouine?
guettli