Как проверить, что проблема в базе данных при высокой нагрузке
Что проверяют
Умеете ли вы доказывать, а не угадывать. Сервис тормозит под нагрузкой, и вопрос в том, разложите ли вы время запроса по слоям и покажете цифрами, где оно уходит. «Наверное, база» без метрик это худший ответ.
Как отвечать
- Сначала со стороны приложения: таймеры Micrometer или APM вокруг репозиториев. Если время внутри вызовов к БД мало, а общее велико, база ни при чём.
- Пул соединений первый подозреваемый. У HikariCP смотрим
hikaricp.connections.pendingи таймер получения соединения: очередь за коннектом выглядит снаружи как «тормозит база», хотя база простаивает. - На стороне PostgreSQL основной инструмент это
pg_stat_statements(total_exec_time,calls,mean_exec_time), а не только лог медленных запросов: типичный N+1 состоит из тысяч быстрых запросов, каждый ниже порогаlog_min_duration_statement. - Ожидания и блокировки:
pg_stat_activityсwait_event_type,pg_blocking_pids(pid)для дерева блокировок, отдельный красный флаг это долгиеidle in transaction. - План конкретного запроса:
EXPLAIN (ANALYZE, BUFFERS), смотрим расхождение оценки и факта по строкам и долю чтений с диска. - Ресурсы хоста БД: CPU,
iostat -x(await, %util), объём shared_buffers. Если CPU базы упёрся при неизменных планах, проблема в количестве запросов, а не в конкретном.
select wait_event_type, wait_event, count(*)
from pg_stat_activity
where state <> 'idle'
group by 1, 2 order by 3 desc;Где спотыкаются
Смотрят только slow log и не находят N+1: по отдельности запросы быстрые, суммарно они и съедают время.
Путают «база нагружена» с «база виновата». Под нагрузкой растут все метрики, нужна причинно-следственная связь, а не корреляция графиков.
Не проверяют пул и таймауты. Маленький пул, отсутствие connectionTimeout и statement_timeout дают лавину ожиданий, которая маскируется под медленную БД.
Делают выводы по одному EXPLAIN без ANALYZE или на прогретом локальном стенде, где данных на два порядка меньше и план другой.