Короткий ответ
Нужно собрать факты о реальном поведении в production — найти конкретный медленный запрос через pg_stat_statements или log_min_duration_statement, снять его реальный план через EXPLAIN (ANALYZE, BUFFERS) на сопоставимых по объёму данных и сравнить с локальной средой по объёму данных, статистике планировщика и настройкам.
Как это работает подробнее
pg_stat_statements агрегирует статистику по нормализованным запросам (общее время, число вызовов, среднее время), что помогает найти «тяжёлые» по суммарному вкладу запросы; log_min_duration_statement логирует отдельные запросы, превысившие порог.
Пример кода
example.sql
SELECT query, calls, total_exec_time, mean_exec_time, rows
FROM pg_stat_statements
ORDER BY total_exec_time DESC
LIMIT 10;
-- Находим самый "дорогой" суммарно запрос, затем снимаем его план:
EXPLAIN (ANALYZE, BUFFERS) SELECT id, user_id, total FROM orders WHERE user_id = 42 ORDER BY created_at DESC LIMIT 50;Что использовать на практике
- Практика. Частая причина разницы между локальной средой и production — объём данных, устаревшая статистика (ANALYZE не выполнялся после массовой загрузки), отсутствующий в локальной БД индекс, конкуренция за ресурсы под реальной нагрузкой.
Подводные камни
- Ошибка. Тестируют гипотезу только через EXPLAIN без ANALYZE — он показывает лишь оценку; делают выводы на локальной БД с тестовыми данными объёмом в сотни строк, когда в production таблица на десятки миллионов строк и план принципиально другой.