Анализ использования индекса PostgreSQL

87

Есть ли инструмент или метод для анализа Postgres и определения того, какие недостающие индексы следует создать, а какие неиспользуемые индексы следует удалить? У меня есть небольшой опыт работы с инструментом «профилировщик» для SQLServer, но я не знаю о подобном инструменте, включенном в Postgres.

Cerin
источник
Так что, это. Давно не смотрел на это. Обновил мой принятый ответ.
Cerin 08

Ответы:

164

Мне нравится находить недостающие индексы:

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 может помочь ...

Геттли
источник
15
Чтобы эта работа работала с указанными в кавычках идентификаторами, измените запрос на: 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
Вывод этого запроса должен быть объяснен, чтобы сделать ответ более полезным
cen
С точки зрения @cen, когда too_much_seqположительный и большой, вы должны быть обеспокоены.
mountainclimber11
1
@KishoreKumar Я думаю, что статистика в postgres все еще содержит запросы, которые были выполнены до того, как вы обновили свой индекс. В зависимости от вашего трафика статистика снова будет в норме через несколько часов.
Guettli
1
::regclassне будет работать с идентификаторами в верхнем регистре, @Mr. Хорошее решение у Ондатры, тоже можно использовать ('"' || relname || '"')::regclassвместо него.
Адриан
10

Подход к определению недостающих индексов .... Нет. Но есть некоторые планы сделать это проще в будущем выпуске, например, псевдоиндексы и машиночитаемый EXPLAIN.

В настоящее время вам нужно выполнить EXPLAIN ANALYZEнеэффективные запросы, а затем вручную определить лучший маршрут. Некоторые анализаторы журналов, такие как pgFouine, могут помочь определить запросы.

Что касается неиспользуемого индекса, вы можете использовать что-то вроде следующего, чтобы помочь идентифицировать их:

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

Это поможет идентифицировать прочитанные, отсканированные, извлеченные кортежи.

rfusca
источник
Фрэнк Хейкенс также указывает несколько хороших мест, где можно узнать о текущем использовании индекса.
rfusca
8

Еще один новый и интересный инструмент для анализа PostgreSQL - PgHero. . Он больше ориентирован на настройку базы данных и предлагает многочисленные анализы и предложения.

снимок экрана

n1000
источник
6

Вы можете использовать запрос ниже, чтобы найти использование индекса и размер индекса:

Ссылка взята из этого блога.

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

Есть несколько ссылок на скрипты, которые помогут вам найти неиспользуемые индексы в вики PostgreSQL . Основной метод состоит в том, чтобы посмотреть pg_stat_user_indexesи найти те idx_scan, в которых счетчик того, сколько раз этот индекс использовался для ответа на запросы, равен нулю или, по крайней мере, очень мал. Если приложение изменилось, а ранее использовавшийся индекс, вероятно, сейчас нет, иногда приходится запускатьpg_stat_reset() чтобы вернуть всю статистику обратно к 0, а затем собрать новые данные; вы можете сохранить текущие значения для всего и вместо этого вычислить дельту, чтобы выяснить это.

Пока что нет хороших инструментов, которые предлагали бы отсутствующие индексы. Один из подходов - регистрировать выполняемые вами запросы и анализировать, выполнение каких из них занимает много времени, с помощью инструмента анализа журнала запросов, такого как pgFouine или pqa. См. « Регистрация сложных запросов. » для получения дополнительной информации.

Другой подход состоит в том, чтобы просматривать pg_stat_user_tablesи искать таблицы с большим количеством последовательных сканирований против них, где они seq_tup_fetchбольшие. Когда используется индекс, idx_fetch_tupвместо этого увеличивается счетчик. Это может подсказать вам, когда таблица недостаточно хорошо проиндексирована, чтобы отвечать на запросы к ней.

Фактически выясняете, какие столбцы вы должны индексировать? Обычно это снова приводит к анализу журнала запросов.

Грег Смит
источник
1

PoWA кажется интересным инструментом для PostgreSQL 9.4+. Он собирает статистику, визуализирует ее и предлагает индексы. Он использует pg_stat_statementsрасширение.

PoWA - это анализатор рабочей нагрузки PostgreSQL, который собирает статистику производительности и предоставляет диаграммы и графики в реальном времени, чтобы помочь контролировать и настраивать ваши серверы PostgreSQL. Он похож на Oracle AWR или SQL Server MDW.

n1000
источник
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 
Маджарди
источник