#Симптом и границы применимости
После перезапуска PostgreSQL запросы временно замедлились, хотя SQL и индексы не менялись. Причиной может быть холодный кэш ОС, изменившаяся статистика или резкий поток подключений; решение начинается с измерений до ручной перестройки индексов.
#Как отличить возможные причины
| Возможная причина | Как узнать | Что делать |
|---|---|---|
| Холодный файловый кэшПосле перезапуска буферы PostgreSQL и файловый кэш ОС постепенно наполняются данными. | Первый запуск медленнее следующих | Сравнить последовательные измерения |
| Устаревшие оценкиПланировщик использует статистику, не отражающую текущие данные. | Изменился план доступа | Проверить last_analyze |
| Наплыв подключенийВсе рабочие процессы одновременно переподключаются после простоя. | Резкий пик числа активных backend | Проверить пул соединений |
#Пошаговая диагностика и безопасное исправление
- 1. Зафиксируйте запрос и объём проблемыИз мониторинга возьмите один медленный SELECT, его параметры, время до и после перезапуска. Разделите постоянное ухудшение и первые запросы после старта; это разные сценарии диагностики.
- 2. Проверьте версию, время работы и число сеансовОткройте psql под учётной записью с достаточными правами на статистику. Сравните число активных и ожидающих подключений, а также время последнего запуска.
- psql, только чтение; без pg_read_all_stats часть сведений о чужих сессиях скрытаSQLКомандаpsql, только чтение; без pg_read_all_stats часть сведений о чужих сессиях скрыта.
SELECT pg_postmaster_start_time(), count(*) AS sessions, count(*) FILTER (WHERE state='active') AS active FROM pg_stat_activity;
- 3. Снимите оценочный план без выполнения тяжёлого запросаВ psql выполните EXPLAIN для реального SELECT, убрав секретные значения. Обычный EXPLAIN даёт план, но EXPLAIN ANALYZE уже выполняет запрос; его оставьте для тестовой среды.SQLКомандаpsql; пример запроса для чтения. Подставьте собственный SELECT и параметры.
EXPLAIN SELECT id FROM app.orders WHERE customer_id=42;
- 4. Посмотрите время обновления статистикиВ pg_stat_user_tables найдите таблицы используемого запроса и даты last_analyze/last_autoanalyze; отсутствие даты не всегда ошибка, но полезный признак.
- psql; чтение статистикиSQLКомандаpsql; чтение статистики. Нули и даты требуют контекста объёма таблицы.
SELECT schemaname, relname, last_analyze, last_autoanalyze, n_mod_since_analyze FROM pg_stat_user_tables WHERE schemaname='app' ORDER BY n_mod_since_analyze DESC LIMIT 20;
- 5. Разделите I/O и ожидания блокировокЕсли запросы ждут блокировки или диск перегружен, не «лечите» их статистикой. Сверьте wait_event_type/ wait_event в pg_stat_activity и системный монитор диска, учитывая права на чтение статистики.
- 6. Проверьте безопасное улучшение на копииЕсли причина в оценках, администратор на тесте может выполнить ANALYZE конкретной таблицы и сравнить новый EXPLAIN с прежним. ANALYZE создаёт нагрузку и не равен VACUUM FULL.SQLС осторожностьюПрава администратораpsql на тестовой базе; обновляет статистику таблицы, имеет цену по I/O. Требует достаточных прав.
ANALYZE app.orders;Команда может изменить состояние системы или её настройки. Проверьте параметры и последствия перед запуском.
- 7. Проверьте прогрев и стабильность планаСравните время трёх последовательных выполнений в тесте, показания кэша и наличие блокировок. Если замедление наблюдается только после рестарта, рассмотрите политику прогрева и нагрузку пула без искусственного полного чтения всех таблиц.
- 8. Выпускайте только подтверждённое исправлениеСогласуйте изменение статистики, параметров или пула и проверьте под реальной нагрузкой. Не делайте REINDEX всей базы по одному медленному запросу — это дорого и часто не связано с причиной.
#Как проверить, что проблема устранена
Время одинаковых запросов стабилизировалось после подтверждённого изменения, показатели ожиданий и I/O нормальны; план зафиксирован до/после.
#Если исправление не помогло
Если время остаётся высоким, проверьте сетевую задержку, число параллельных соединений, дисковую подсистему и блокировки; приложите реальный EXPLAIN и статистику.