# Карта pg_stat_* и pg_stat_statements _Эксплуатация и наблюдаемость · PostgreSQL Knowledge Base_ **TL;DR:** Системные представления pg_stat_* - встроенный мониторинг PostgreSQL. pg_stat_activity показывает, кто что делает прямо сейчас; pg_stat_*_tables и pg_statio_* - накопленную статистику по таблицам; pg_stat_statements - агрегат по нормализованным запросам, главный инструмент поиска медленного SQL. ## Две природы статистики Представления `pg_stat_*` делятся на два сорта, и путать их - частая ошибка при диагностике. - **Мгновенный снимок** - что происходит сейчас. `pg_stat_activity` (по строке на backend), `pg_locks`, `pg_stat_replication` (см. [streaming-replication](/courses/postgres/kb/streaming-replication.md)), `pg_stat_progress_vacuum`. Читаешь - видишь текущее состояние. - **Накопленные счётчики** - сумма с момента сброса статистики. `pg_stat_user_tables`, `pg_statio_user_tables`, `pg_stat_database`, `pg_stat_statements`. Само число мало о чём говорит; смысл - в разнице двух замеров (дельте) за интервал. Главное следствие: по накопленным счётчикам нельзя сказать «сейчас плохо». Можно сказать «за час между замерами выросло вот это». ## Кто что делает прямо сейчас `pg_stat_activity` - первый экран при «база тормозит». Строка на каждое соединение: `state` (`active` / `idle` / `idle in transaction`), текущий `query`, время начала, `wait_event`. ```sql -- активные дольше 30 секунд и зависшие в транзакции SELECT pid, state, wait_event_type, wait_event, now() - xact_start AS xact_age, left(query, 60) AS q FROM pg_stat_activity WHERE state <> 'idle' ORDER BY xact_age DESC NULLS LAST; ``` `idle in transaction` с большим `xact_age` - тревога: такой backend держит горизонт (см. [transaction-horizon](/courses/postgres/kb/transaction-horizon.md)) и мешает vacuum, даже ничего не делая. ## Здоровье таблиц `pg_stat_user_tables` отвечает на «нужен ли vacuum» и «берётся ли индекс»: `n_live_tup`/`n_dead_tup`, `last_autovacuum`, `seq_scan` против `idx_scan`. `pg_statio_user_tables` - про кеш: `heap_blks_hit` против `heap_blks_read` - попадания в буфер против чтений с диска (см. [buffer-states](/courses/postgres/kb/buffer-states.md)). ## Поиск медленного SQL: pg_stat_statements Расширение агрегирует выполнение по **нормализованному** тексту: запросы `WHERE id = 1` и `WHERE id = 2` схлопываются в один `WHERE id = $1`. Поэтому одно тяжёлое место видно как одна строка с суммой по всем вызовам - в отличие от лога, где это тысячи отдельных записей. ```sql SELECT queryid, calls, round(total_exec_time) AS total_ms, round(mean_exec_time, 1) AS mean_ms, left(query, 70) AS q FROM pg_stat_statements ORDER BY total_exec_time DESC LIMIT 10; ``` Сортируй по `total_exec_time` (суммарное время), а не по `mean` - запрос на 2 мс, вызванный миллион раз, съедает больше, чем разовый отчёт на 10 секунд. Это и есть «виновник» нагрузки. Дополняет картину `log_min_duration_statement` - порог, выше которого каждый медленный запрос пишется в лог сервера целиком, с параметрами. pg_stat_statements говорит «какой класс запросов жрёт время», лог - «вот конкретный вызов с этими значениями». Дальше: настройка памяти под найденные запросы - [memory-config](/courses/postgres/kb/memory-config.md); переписывание плохих запросов - [anti-patterns](/courses/postgres/kb/anti-patterns.md). ## Команды ```sql SELECT pid, state, wait_event, query FROM pg_stat_activity WHERE state <> 'idle'; ``` Кто активен прямо сейчас и чего ждёт ```sql SELECT query, calls, total_exec_time FROM pg_stat_statements ORDER BY total_exec_time DESC LIMIT 10; ``` Топ запросов по суммарному времени - главный отчёт о нагрузке ```sql SELECT relname, n_dead_tup, last_autovacuum FROM pg_stat_user_tables ORDER BY n_dead_tup DESC; ``` Где копится мусор и когда autovacuum приходил в последний раз ```sql SELECT pg_stat_statements_reset(); ``` Сбросить счётчики, чтобы мерить дельту за чистый интервал ## См. также - [Конфигурация памяти в контексте механизма](/courses/postgres/kb/memory-config.md) - [Каталог анти-паттернов (cheat sheet)](/courses/postgres/kb/anti-patterns.md) - [Backup и восстановление на точку (PITR)](/courses/postgres/kb/backup-pitr.md) - [Горизонт транзакции](/courses/postgres/kb/transaction-horizon.md) - [Четыре состояния буфера](/courses/postgres/kb/buffer-states.md)