Сталкивались ли вы с проблемами оптимизации запросов
Что проверяют
Есть ли у вас реальный опыт диагностики, а не только знание слова «индекс». Интервьюер ждёт историю, где видно, как вы нашли медленный запрос, чем подтвердили причину и как измерили результат. Следом обычно просят разобрать план выполнения или спрашивают про N+1 в Hibernate.
Как отвечать
Возьмите один случай из своей практики и расскажите по шагам: симптом, диагностика, исправление, замер. Для Java с PostgreSQL опорные точки такие:
- поиск виновника:
pg_stat_statementsсортирует запросы по суммарному времени,log_min_duration_statementиauto_explainловят медленные в логах. В приложении включают логированиеorg.hibernate.SQLилиdatasource-proxy, чтобы увидеть, сколько запросов уходит на один HTTP-вызов; - план:
EXPLAIN (ANALYZE, BUFFERS)с реальным временем. Смотрите наSeq Scanпо большой таблице, расхождение оценки и факта вrows,Nested Loopс тысячами итераций, сортировку на диске; - N+1: самая частая беда JPA. Лечится
JOIN FETCH,@EntityGraphилиhibernate.default_batch_fetch_size, а для списков на чтение лучше DTO-проекции; - индексы: составной под фильтр и сортировку, индекс по выражению для
lower(email), частичный под частый фильтр; - пагинация:
OFFSET 100000читает и выбрасывает сто тысяч строк, keyset-пагинация по(created_at, id)от глубины не зависит; - запись: пакетная вставка через
hibernate.jdbc.batch_size.
Закончите цифрой и способом замера: «p95 эндпоинта упал с 1,8 с до 120 мс, запросов на страницу стало 2 вместо 101». Если такого опыта не было, скажите прямо и покажите, как бы действовали, на учебном проекте с настоящим планом запроса.
Где спотыкаются
Отвечают «добавил индекс» без плана до и после. EXPLAIN без ANALYZE показывает только оценки планировщика, и не видно, помог ли индекс вообще.
Лечат N+1 через FetchType.EAGER. Лишние запросы никуда не деваются, просто начинают уходить везде, где грузится сущность.
Не знают ловушек Hibernate: при GenerationType.IDENTITY пакетная вставка отключается, а JOIN FETCH коллекции вместе с setMaxResults пагинирует в памяти, выгружая всю выборку и оставляя в логе лишь предупреждение.