Analisi dell'utilizzo dell'indice PostgreSQL


88

Esiste uno strumento o un metodo per analizzare Postgres e determinare quali indici mancanti dovrebbero essere creati e quali indici inutilizzati dovrebbero essere rimossi? Ho un po 'di esperienza con lo strumento "profiler" per SQL Server, ma non sono a conoscenza di uno strumento simile incluso con Postgres.

Risposte:


166

Mi piace questo per trovare gli indici mancanti:

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;

Questo controlla se sono presenti più scansioni di sequenza rispetto a scansioni di indice. Se la tabella è piccola, viene ignorata, poiché Postgres sembra preferire le scansioni in sequenza per loro.

La query sopra mostra gli indici mancanti.

Il passaggio successivo consiste nel rilevare gli indici combinati mancanti. Immagino che non sia facile, ma fattibile. Forse analizzando le query lente ... ho sentito che pg_stat_statements potrebbe aiutare ...


17
Per fare in modo che funzioni con identificatori citati, modificare la query in: 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;
Sig. Muskrat

Per il punto di @cen, quando too_much_seqè positivo e grande dovresti essere preoccupato.
mountainclimber11

Ho creato pochi indici su una delle tabelle, ma ancora, questa query mostra gli indici mancanti su quella tabella.
Kishore Kumar

1
@KishoreKumar Immagino che le statistiche in postgres contengano ancora le query eseguite prima dell'aggiornamento dell'indice. A seconda del traffico, le statistiche torneranno a essere corrette dopo alcune ore.
guettli

1
::regclassnon funzionerà con identificatori maiuscoli, @Mr. Topo muschiato ha una buona soluzione, è anche possibile utilizzare al suo ('"' || relname || '"')::regclassposto.
Adrien


10

Sull'approccio per determinare gli indici mancanti .... No. Ma ci sono alcuni piani per renderlo più semplice nelle versioni future, come gli pseudoindici e EXPLAIN leggibile dalla macchina.

Al momento, dovrai EXPLAIN ANALYZEeseguire query con scarso rendimento e quindi determinare manualmente il percorso migliore. Alcuni analizzatori di log come pgFouine possono aiutare a determinare le query.

Per quanto riguarda un indice inutilizzato, puoi utilizzare qualcosa di simile al seguente per identificarli:

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

Ciò aiuterà a identificare le tuple lette, scansionate, recuperate.


8

Un altro strumento nuovo e interessante per analizzare PostgreSQL è PgHero . È più focalizzato sulla messa a punto del database e fornisce numerose analisi e suggerimenti.

immagine dello schermo


6

È possibile utilizzare la query seguente per trovare l'utilizzo dell'indice e la dimensione dell'indice:

Il riferimento è tratto da questo 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;

4

Ci sono più collegamenti agli script che ti aiuteranno a trovare indici inutilizzati nel wiki di PostgreSQL . La tecnica di base è guardare pg_stat_user_indexese cercare quelli in cui idx_scan, il conteggio di quante volte quell'indice è stato utilizzato per rispondere alle domande, è zero, o almeno molto basso. Se l'applicazione è cambiata e un indice precedentemente utilizzato probabilmente non lo è ora, a volte è necessario eseguirepg_stat_reset() per riportare tutte le statistiche a 0 e quindi raccogliere nuovi dati; potresti salvare i valori correnti per tutto e calcolare un delta invece per capirlo.

Non sono ancora disponibili buoni strumenti per suggerire indici mancanti. Un approccio consiste nel registrare le query che stai eseguendo e analizzare quali richiedono molto tempo per essere eseguite utilizzando uno strumento di analisi del registro delle query come pgFouine o pqa. Vedere " Registrazione di query difficili " per maggiori informazioni.

L'altro approccio consiste nel guardare pg_stat_user_tablese cercare le tabelle che hanno un gran numero di scansioni sequenziali su di esse, dove seq_tup_fetchè grande. Quando viene utilizzato un indice, il idx_fetch_tupconteggio viene invece aumentato. Questo può indurti a capire quando una tabella non è indicizzata abbastanza bene per rispondere alle domande contro di essa.

Stai davvero cercando di capire su quali colonne dovresti indicizzare? Questo di solito riconduce alla roba di analisi del log delle query.



1

PoWA sembra uno strumento interessante per PostgreSQL 9.4+. Raccoglie statistiche, le visualizza e suggerisce indici. Usa l' pg_stat_statementsestensione.

PoWA è PostgreSQL Workload Analyzer che raccoglie statistiche sulle prestazioni e fornisce grafici e grafici in tempo reale per aiutare a monitorare e ottimizzare i tuoi server PostgreSQL. È simile a Oracle AWR o 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 
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.