Отчёт по успеваемости класса собирался полторы минуты
Сберкласс · Сберобразование · 2023
Задача
Учитель открывал сводку по классу и ждал полторы минуты. В учебные часы такие запросы шли пачками и отъедали CPU у основной базы, а вместе с ним подтормаживала и выдача заданий ученикам — основной сценарий платформы. Жаловались при этом абстрактно: «платформа тупит», про сам отчёт никто не упоминал.
Что сделал
- Нашёл реальный источник нагрузки: не гадал, а взял
pg_stat_statementsи отсортировал по суммарному времени. Верхние строки — не сам отчёт, а 5 выборок вокруг него. - Прогнал их через
EXPLAIN (ANALYZE, BUFFERS). Классический N+1: на каждого ученика уходил отдельный запрос за результатами, плюс Hibernate поднимал в память граф сущностей, из которого нужны были три поля. - Там, где маппинг в сущности был лишним, перевёл выборки на
JdbcTemplateс плоской проекцией. Не «отказался от ORM» — заменил ровно те места, где ORM мешал. - Добавил составные индексы под фактические предикаты (проверил, что планировщик их действительно берёт, а не игнорирует).
- Ночные агрегаты вынес в materialized view с обновлением по расписанию: свежесть данных на сутки — приемлемая цена, отчёт за прошлый период не обязан быть онлайновым.
Результат
Отчёт стал собираться за 12 секунд вместо 90. Но главным был даже не сам отчёт: тяжёлые аналитические запросы перестали конкурировать с боевой нагрузкой, и жалобы на тормоза в учебные часы прекратились.