pg_stat_statements — это встроенное расширение PostgreSQL, которое позволяет следить за тем, какие запросы на самом деле происходят в базе данных и как они себя ведут. По сути, это такой тихий, но наблюдательный помощник, который фиксирует каждый шаг: какие SQL-запросы выполнялись, сколько времени они заняли, как часто запускались и насколько нагружали систему.
Зачем это нужно? Во-первых, чтобы находить проблемные запросы. Иногда база тормозит не из-за одного злодея, а из-за десятка одинаковых тяжёлых запросов, которые выполняются слишком часто. Во-вторых, статистика помогает увидеть, какие именно запросы съедают ресурсы — процессор, память, диск. А ещё вы можете понять, работают ли индексы так, как вы планировали: может быть, где-то они не используются вообще, а где-то — наоборот, не хватает.
pg_stat_statements позволяет не гадать, а видеть реальные цифры — и на их основе делать выводы и оптимизации.
Как найти медленные запросы?
Теперь начинается самое интересное! Используя таблицу pg_stat_statements, мы можем искать запросы, которые выполняются долго или сильно нагружают сервер.
Основная идея:
Каждая строка в таблице pg_stat_statements представляет статистику по одному запросу. Запросы группируются по их тексту (собственно, поле query), и для каждого из них подсчитываются следующие метрики:
total_time— общее время выполнения запроса, в миллисекундах.calls— количество выполнений запроса.mean_time— среднее время выполнения запроса (total_time / calls).rows— количество строк, которые возвращал запрос.
Пример простого анализа
Попробуем найти самые медленные запросы по среднему времени выполнения:
SELECT
query,
mean_time,
calls,
rows
FROM
pg_stat_statements
ORDER BY
mean_time DESC
LIMIT 5;
Этот запрос покажет ТОП-5 запросов, которые выполняются дольше всего. Обратите внимание на поле mean_time: если там значения в миллисекундах переваливают за 500-1000, это сигнал к тому, что запросы нужно оптимизировать.
Пример анализа медленных запросов
Давайте разберём пример:
Вот результат выполнения предыдущего запроса:
| query | mean_time | calls | rows |
|---|---|---|---|
| SELECT * FROM orders WHERE status = 'new'; | 1234.56 | 10 | 10000 |
| SELECT * FROM products | 755.12 | 5000 | 100 |
| SELECT * FROM customers WHERE id = $1 | 543.21 | 1000 | 1 |
Что мы видим?
Запрос к таблице orders: выполняется очень редко (всего 10 вызовов), но каждый раз тянет огромные 10 тысяч строк. Наверное, таблица очень большая, и запрос не использует индексы.
Запрос к таблице products: вызывается миллионы раз, возможно, в цикле в приложении. Каждая выборка возвращает всего 100 строк, но из-за частоты этот запрос тоже может быть проблемой.
Запрос к таблице customers: выполняется быстро (543 мс), но вызывается слишком часто.
Оптимизация медленных запросов
Теперь, когда мы нашли проблемные запросы, нужно посмотреть их план выполнения с помощью EXPLAIN ANALYZE. Например, для запроса к таблице orders:
EXPLAIN ANALYZE
SELECT * FROM orders WHERE status = 'new';
Что мы можем увидеть?
Seq Scan: если запрос использует последовательное сканирование, нужно добавить индекс:
CREATE INDEX idx_orders_status ON orders (status);
Проблемы с фильтрацией: если запрос тянет слишком много строк, пересмотрите сам текст запроса. Возможно, нужно добавить дополнительные условия или лимитировать результаты:
SELECT * FROM orders WHERE status = 'new' LIMIT 100;
Вывод статистики по времени выполнения
Иногда проблемные запросы могут быть не такими очевидными. Например, запросы, которые часто вызывают функции или подзапросы. В таких случаях удобно смотреть столбец total_time:
SELECT
query,
total_time,
calls,
mean_time
FROM
pg_stat_statements
ORDER BY
total_time DESC
LIMIT 10;
Этот запрос покажет самые "дорогие" запросы по суммарному времени выполнения.
Оптимизация индексации
Часто медленные запросы связаны с отсутствием необходимых индексов. Используйте pg_stat_statements, чтобы понять, какие запросы не используют индексы. Если вы видите много запросов с одинаковыми фильтрами (например, по полю status), но они очень медленные, добавьте соответствующий индекс:
CREATE INDEX idx_orders_status ON orders (status);
После этого проверьте производительность запроса снова с EXPLAIN ANALYZE.
Используя pg_stat_statements, вы можете эффективно следить за производительностью запросов, находить "узкие места" и улучшать производительность вашей базы данных. Помните, что чем раньше вы начнёте анализировать запросы, тем проще будет оптимизировать работу всей системы.
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ