Кейс: экспорт в Excel падал на файлах больше 50 тысяч строк

Сервис генерировал отчёты в xlsx через Apache POI. На небольших выгрузках всё работало — тестировали на паре тысяч строк. В проде клиент выгрузил отчёт за год, около 200 тысяч строк, и под упал по памяти.

Причина — обычный XSSFWorkbook держит всю структуру книги в памяти как объектный граф: строки, ячейки, стили — всё живёт в куче до вызова write(). На 200 тысячах строк с несколькими столбцами это легко уходило за гигабайт при том, что сам файл на диске весил в разы меньше.

Переписали на SXSSFWorkbook — потоковая версия POI, которая держит в памяти только последние N строк (задаётся окном), а остальные сразу сбрасывает во временный файл на диске. Память перестала расти с размером отчёта.

try (SXSSFWorkbook workbook = new SXSSFWorkbook(100)) { Sheet sheet = workbook.createSheet(); for (int i = 0; i < rowCount; i++) { Row row = sheet.createRow(i); fillRow(row, data.get(i)); } workbook.write(outputStream); }

Второй нюанс, который всплыл после фикса: SXSSFWorkbook не даёт читать уже сброшенные на диск строки — формулы, которые ссылаются на далёкие ячейки выше окна, перестают работать корректно. Пришлось убрать все межстрочные формулы из шаблона и считать агрегаты на стороне сервиса до генерации файла.

Поведение библиотеки «в памяти всё храним» безопасно ровно до того размера данных, на котором тестировали, и ни строкой больше.

Тренажёр: 600 вопросов, мок с таймером, план повторов

senior·base — что спрашивают на самом деле


В этом посте были ссылки, но мы их удалили по правилам Сетки