Экспорт большого объёма данных (> 2Гб)
Здравствуйте.
Настал момент, когда заказчик захотел выгрузить огромный объём данных (порядка 3х млн. записей) в файл (в PDF).
Проблема заключается в том, что когда по такому объёму данных начинает строиться FastReport-отчёт - приложению банально не хватает памяти - упираемся в потолок для 32х битного приложения 2Гб.
Сами данные после выборки (если их выбрать все) занимают чуть меньше 1Гб, а когда по ним начинает строиться отчёт - каждая запись "обрастает" объектами типа TfrxMemo и память заканчивается мгновенно.
Допустим, мы загрзимся с опцией /3Gb в boot.ini. Допустим мы не будем выбирать все данные из БД на клиент (пусть курсор будет однонаправленный - данные будут выбираться порциями). Возможно памяти хватит, чтобы построить отчёт. Но его ещё нужно выгрузить (экспортировать в PDF).
Выпустить 64х-сборку приложения сейчас нет возможности (это новая версия Delphi, которую надо покупать - это планируется, но ещё не скоро это произойдёт, а потом ещё адаптация исходников - тоже неизвестно на какое время). А PDF-файл (ну или файлы) заказчик хочет уже сейчас.
Первое, что приходит в голову - это сделать экспорт в несколько файлов по какому-нибудь критерию (например тупо по количеству страниц) - заказчик на это соглашается. Однако хочется это сделать внутри самого скрипта отчёта.
Я начал "пробрасывать" в скриптовую систему функции, которые бы могли "по-тихому" экспортировать построенный отчёт в выбранный формат. Но я пока не понимаю, как экспортировать отчёт не после его построения, а экспортировать порциями в процессе построения.
Т.е. я хочу, чтобы: отчёт построился на N-страниц, затем произошёл экспорт в файл, затем очищаем отчёт (чтобы освободить память, иначе может настать момент, когда и /3Gb не хватит), затем строим следующие N-страниц и делаем экспорт, и так далее, пока приходят данные из БД.
Вопрос:
Есть ли готовые решения, или может быть кто-нибудь сталкивался с подобной задачей?
Повторюсь, хотелось бы реализовать это всё средствами скриптовой части самого отчёта - это было бы прозрачно для разработчика отчёта и понятно для пользователя.
В крайнем случае, можно запустить формирование отчёта в неком обработчике, который бы контролировал процесс построения и делал бы экспорт каждые N-страниц, но такой вариант (хоть он и проще в реализации) мне не нравится впринципе.
Настал момент, когда заказчик захотел выгрузить огромный объём данных (порядка 3х млн. записей) в файл (в PDF).
Проблема заключается в том, что когда по такому объёму данных начинает строиться FastReport-отчёт - приложению банально не хватает памяти - упираемся в потолок для 32х битного приложения 2Гб.
Сами данные после выборки (если их выбрать все) занимают чуть меньше 1Гб, а когда по ним начинает строиться отчёт - каждая запись "обрастает" объектами типа TfrxMemo и память заканчивается мгновенно.
Допустим, мы загрзимся с опцией /3Gb в boot.ini. Допустим мы не будем выбирать все данные из БД на клиент (пусть курсор будет однонаправленный - данные будут выбираться порциями). Возможно памяти хватит, чтобы построить отчёт. Но его ещё нужно выгрузить (экспортировать в PDF).
Выпустить 64х-сборку приложения сейчас нет возможности (это новая версия Delphi, которую надо покупать - это планируется, но ещё не скоро это произойдёт, а потом ещё адаптация исходников - тоже неизвестно на какое время). А PDF-файл (ну или файлы) заказчик хочет уже сейчас.
Первое, что приходит в голову - это сделать экспорт в несколько файлов по какому-нибудь критерию (например тупо по количеству страниц) - заказчик на это соглашается. Однако хочется это сделать внутри самого скрипта отчёта.
Я начал "пробрасывать" в скриптовую систему функции, которые бы могли "по-тихому" экспортировать построенный отчёт в выбранный формат. Но я пока не понимаю, как экспортировать отчёт не после его построения, а экспортировать порциями в процессе построения.
Т.е. я хочу, чтобы: отчёт построился на N-страниц, затем произошёл экспорт в файл, затем очищаем отчёт (чтобы освободить память, иначе может настать момент, когда и /3Gb не хватит), затем строим следующие N-страниц и делаем экспорт, и так далее, пока приходят данные из БД.
Вопрос:
Есть ли готовые решения, или может быть кто-нибудь сталкивался с подобной задачей?
Повторюсь, хотелось бы реализовать это всё средствами скриптовой части самого отчёта - это было бы прозрачно для разработчика отчёта и понятно для пользователя.
В крайнем случае, можно запустить формирование отчёта в неком обработчике, который бы контролировал процесс построения и делал бы экспорт каждые N-страниц, но такой вариант (хоть он и проще в реализации) мне не нравится впринципе.
Комментарии
Например в обработчике (в скрипте отчёта) TfrxReport.OnStopReport я теперь могу написать что-то типа такого: и экспорт отрабатывает после построения отчёта.
Впринципе, экспорт работает вообще в любой момент времени, даже в процессе построения - например в обработчике AfterPrint какого-нибудь объекта.
Однако попытки удалить уже построенные (и экспортрованные) PreviewPages приводят к разного рода AccessViolation'ам
Вот это для меня сейчас проблемно - корректно скзать типа ReportStop, потом очистить страницы, и сказать ReportStart (но не с начала, а как бы продолжить построение).