Analiza wykorzystania indeksu PostgreSQL

87

Czy istnieje narzędzie lub metoda do analizy Postgres i określenia, które brakujące indeksy należy utworzyć, a które nieużywane indeksy usunąć? Mam niewielkie doświadczenie w robieniu tego z narzędziem „profiler” dla SQLServer, ale nie znam podobnego narzędzia dołączonego do Postgres.

Cerin
źródło
Tak to jest. Nie patrzyłem na to od jakiegoś czasu. Zaktualizowałem zaakceptowaną odpowiedź.
Cerin

Odpowiedzi:

164

Lubię to, aby znaleźć brakujące indeksy:

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;

Sprawdza, czy jest więcej skanowań sekwencji niż indeksów. Jeśli tabela jest mała, jest ignorowana, ponieważ Postgres wydaje się preferować skanowanie sekwencyjne.

Powyższe zapytanie ujawnia brakujące indeksy.

Następnym krokiem byłoby wykrycie brakujących indeksów połączonych. Myślę, że nie jest to łatwe, ale wykonalne. Może analiza wolnych zapytań ... Słyszałem, że pg_stat_statements może pomóc ...

guettli
źródło
15
Aby to działało z cytowanymi identyfikatorami, zmień zapytanie na: 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;
Mr. Muskrat
10
Wyjście z tego zapytania powinny być wyjaśnione, aby odpowiedź bardziej pomocne
CEN
Do punktu @cen, kiedy too_much_seqjest pozytywne i duże, powinieneś się martwić.
mountainclimber11
1
@KishoreKumar Wydaje mi się, że statystyki w postgres nadal zawierają zapytania, które zostały wykonane przed aktualizacją indeksu. W zależności od ruchu, statystyki znów będą w porządku po kilku godzinach.
guettli
1
::regclassnie będzie działać z identyfikatorami wielkimi literami, @Mr. Piżmak ma dobre rozwiązanie, można go również użyć ('"' || relname || '"')::regclasszamiast niego.
Adrien
21

Sprawdź statystyki. pg_stat_user_tablesi pg_stat_user_indexesod których należy zacząć.

Zobacz „ Kolektor statystyk ”.

Frank Heikens
źródło
10

Podejście do określenia brakujących indeksów ... Nie. Ale są pewne plany, aby ułatwić to w przyszłym wydaniu, takie jak pseudoindeksy i czytelne maszynowo EXPLAIN.

Obecnie musisz EXPLAIN ANALYZEwykonywać zapytania o niskiej wydajności, a następnie ręcznie określić najlepszą trasę. Niektóre analizatory dzienników, takie jak pgFouine, mogą pomóc w określeniu zapytań.

Jeśli chodzi o nieużywany indeks, możesz użyć czegoś takiego jak poniżej, aby je zidentyfikować:

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

Pomoże to zidentyfikować przeczytane, zeskanowane, pobrane krotki.

rfusca
źródło
Frank Heikens wskazuje również kilka dobrych miejsc i innych miejsc, w których można zapytać o bieżące użycie indeksu.
rfusca
8

Kolejnym nowym i interesującym narzędziem do analizy PostgreSQL jest PgHero . Bardziej koncentruje się na dostrajaniu bazy danych i przedstawia liczne analizy i sugestie.

zrzut ekranu

n1000
źródło
6

Możesz użyć poniższego zapytania, aby znaleźć użycie indeksu i rozmiar indeksu:

Odniesienie pochodzi z tego bloga.

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
źródło
4

Istnieje wiele linków do skryptów, które pomogą Ci znaleźć nieużywane indeksy na wiki PostgreSQL . Podstawową techniką jest przyjrzenie się pg_stat_user_indexesi wyszukanie tych idx_scan, w których liczba, ile razy ten indeks został użyty do udzielenia odpowiedzi na zapytania, wynosi zero lub przynajmniej jest bardzo niska. Jeśli aplikacja uległa zmianie, a poprzednio używany indeks prawdopodobnie nie jest teraz, czasami trzeba uruchomić pg_stat_reset()wszystkie statystyki z powrotem do 0, a następnie zebrać nowe dane; możesz zapisać aktualne wartości wszystkiego i zamiast tego obliczyć różnicę, aby to rozgryźć.

Nie ma jeszcze żadnych dobrych narzędzi sugerujących brakujące indeksy. Jedną z metod jest rejestrowanie zapytań, które uruchamiasz i analizowanie, które z nich zajmują dużo czasu, za pomocą narzędzia do analizy dziennika zapytań, takiego jak pgFouine lub pqa. Aby uzyskać więcej informacji, zobacz „ Rejestrowanie trudnych zapytań ”.

Innym podejściem jest przyjrzenie się pg_stat_user_tablesi wyszukanie tabel, które mają dużą liczbę sekwencyjnych skanów, gdzie seq_tup_fetchjest duża. Gdy używany jest indeks, idx_fetch_tupzamiast tego liczba jest zwiększana. Może to wskazać, kiedy tabela nie jest indeksowana wystarczająco dobrze, aby odpowiadać na zapytania.

Właściwie zastanawiasz się, które kolumny należy następnie indeksować? Zwykle prowadzi to z powrotem do analizy dziennika zapytań.

Greg Smith
źródło
1

PoWA wydaje się być interesującym narzędziem dla PostgreSQL 9.4+. Zbiera statystyki, wizualizuje je i proponuje indeksy. Używa pg_stat_statementsrozszerzenia.

PoWA to PostgreSQL Workload Analyzer, który gromadzi statystyki wydajności i dostarcza wykresy i wykresy w czasie rzeczywistym, aby pomóc w monitorowaniu i dostrajaniu serwerów PostgreSQL. Jest podobny do Oracle AWR lub SQL Server MDW.

n1000
źródło
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
źródło
-1

To powinno pomóc: Praktyczna analiza zapytań

João Pereira
źródło
1
Ostatnia aktualizacja PQA ma kilka lat. Czy jest to funkcja, która nie jest obsługiwana przez pgFouine?
guettli