Долгие запросы при работе с БД могут вызвать много проблем, кроме очевидной — замедление работы приложения, длительные запросы могут привести к дедлокам, и даже ошибкам если время выполнения превышает таймаут. Поиск медленно работающих запросов — это первый шаг с которого надо начинать решение этих проблем.
Таблица pg_stat_activity
Первый и самый простой способ — использовать pg_stat_activity. Там можно узнать, что происходит в базе в данный
момент.
SELECT pid,
now() - query_start AS duration,
query,
wait_event_type, -- (Lock - ожидание блокировки, IO - диск, Client - клиент долго читает данные)
wait_event,
state
FROM pg_stat_activity
WHERE (now() - query_start) > interval '00:00:02'
AND state = 'active'
ORDER BY duration DESC; -- покажет все активные запросы, которые выполняются дольше 2 секунд
Представление pg_stat_statements
Дальше стоит воспользоваться pg_stat_statements. Она собирает статистику по запросам, с момента
старта сервера БД или последнего сброса статистики, например сколько раз выполнялся запрос, сколько времени занял,
сколько страниц прочитал и т.д.
Это расширение PostgreSQL, которое по умолчанию не включено. Надо проверить postgresql.conf
и добавить если ещё нет строчку: shared_preload_libraries = 'pg_stat_statements'. После добавления
строки надо обязательно перезапустить сервер и создайте расширение запросом:
CREATE EXTENSION IF NOT EXISTS pg_stat_statements;
После этого станет доступно расширенное исследование запросов.
SELECT query,
calls,
mean_exec_time, -- среднее время выполнения в миллисекундах (если показатель большой стоит исследовать с EXPLAIN)
total_exec_time,
rows
FROM pg_stat_statements
ORDER BY mean_exec_time DESC
LIMIT 10;
Важный момент — если расширение только включено, стоит подождать хотя бы сутки чтобы собрались данные для статистики, по началу они могут быть неточными.
Логирование медленных запросов
В PostgreSQL можно включить логирование запросов, которые работают дольше определённого времени.
В postgresql.conf нужно найти настройку и указать время в миллисекундах
log_min_duration_statement = 1000 — будут писаться в лог все запросы выполнявшиеся больше 1 секунды.
Но у этой практики есть минус — логирование добавляет дополнительную нагрузку, соответственно перед включением в production, стоит проверить на тесте.
Что ещё можно проверить
Есть не очевидный способ проверить есть ли проблема в запросах. Когда запросу требуется больше оперативной памяти
чем выделено, PostgreSQL будет использовать временные файлы на диске, а это существенно замедлит работу. Это
значит что проводя исследование запросов также полезно смотреть и статистику CPU, памяти и дисковой активности. В
этом помогут iostat, vmstat, htop и т.п.