Как искать плохие запросы в базе данных
Что проверяют
Есть ли у вас рабочий порядок действий, когда прод тормозит, а не только знание слова EXPLAIN. Следом обычно просят разобрать план конкретного запроса или рассказать, как вы ловили N+1 в Hibernate.
Как отвечать
Сначала найти подозреваемых, потом разбирать каждого. На примере PostgreSQL:
pg_stat_statements: статистика по нормализованным запросам. Сортировка поtotal_exec_timeпоказывает, что грузит базу суммарно, поmean_exec_timeчто медленно само по себе. Подключается черезshared_preload_libraries;- лог медленных запросов:
log_min_duration_statementв PostgreSQL,slow_query_logиlong_query_timeв MySQL. Модульauto_explainпишет в лог сразу и план; pg_stat_activityи блокировки: что выполняется прямо сейчас и кто кого ждёт;EXPLAIN (ANALYZE, BUFFERS): разбор одного запроса. ИщутSeq Scanпо большой таблице, расхождение оценки строк с фактом, сортировку на диске.
Со стороны Java покажите, что видите запросы глазами приложения. Hibernate генерирует SQL сам, поэтому включают hibernate.generate_statistics или прокси вроде datasource-proxy и p6spy и считают запросы на один HTTP-вызов. Метрики пула HikariCP и трассировка через Micrometer или OpenTelemetry показывают, в каком эндпоинте время уходит в базу.
Типичные находки: N+1 из-за ленивых связей (лечится JOIN FETCH или @EntityGraph), выборка всех колонок ради одной, пагинация через большой OFFSET, фильтр без подходящего индекса.
Где спотыкаются
Начинают с EXPLAIN на случайном запросе. Без статистики вы оптимизируете то, что бросилось в глаза, а не то, что грузит базу.
Запускают EXPLAIN ANALYZE на UPDATE или DELETE в проде и забывают, что запрос реально выполнится. Такое оборачивают в транзакцию с ROLLBACK.
Смотрят только на медленные запросы и пропускают быстрые, но частые: запрос на 2 мс, вызванный миллион раз, съедает больше, чем минутный отчёт.