Универсальный загрузчик XML на java. Или как загрузить файлы ГАР на 250 гб и остаться при памяти
С проблемой загрузки больших XML столкнулся при переходе с КЛАДР и ФИАС на справочники ГАР — Государственный адресный реестр (Федеральная информационная адресная система).
Справочник ГАР содержит более подробную информацию чем предыдущие классификаторы. В том числе информацию по муниципальным делениям. В связи с чем справочник после распаковки занимет около 250 ГБ, что примерно в 3 раза больше чем тот же ФИАС.
Предыдущая загрузка работала на DOM-модели, т. е. весь XML-файл считывался в память. Соответственно при попытке загрузить ГАР таким же способом стали стабильно получать OutOfMemory. А значит настало время менять подход к загрузке)
Немного теории:
DOM (Document Object Model) — это стандартный интерфейс для работы с документами в формате XML (Extensible Markup Language). DOM-модель представляет XML-документ в виде дерева объектов, где каждый элемент и атрибут документа является узлом дерева.
SAX (Simple API for XML) является событийно-ориентированным API для чтения XML-документа. Он предоставляет возможность читать XML-документ последовательно и обрабатывать события, такие как начало и конец элемента, содержимое элемента и т. д.
StAX (Streaming API for XML) также является API для последовательного чтения и записи XML-документов. Он предоставляет потоковый доступ к XML-документу, позволяя читать его и записывать по частям. StAX предоставляет возможность читать и записывать XML-документы в виде потока событий, аналогично SAX, но также предоставляет возможность читать и записывать XML-документы в виде итерируемых наборов событий. StAX позволяет эффективно обрабатывать большие XML-документы и не требует реализации обработчиков событий.
Другими словами:
Загрузка XML-документа с помощью DOM-модели довольно медленная, особенно для больших документов, поскольку требует создания полной структуры DOM в памяти. Однако, DOM-модель позволяет легко и удобно работать с XML-документами, поэтому она широко используется в Java-приложениях.
SAX и StAX позволяет обрабатывать XML-документы любого размера, поскольку он не хранит всю структуру в памяти. Однако, для работы необходимо реализовать обработчики событий.
Одним из главных преимуществ использования StAX является его скорость работы и эффективность. И и отличие от DOM, который загружает весь XML-документ в память перед его обработкой, StAX-парсер обрабатывает XML-документ по одному элементу за раз, что позволяет работать с большими XML-файлами.
Понятно. Останавливаемся на StAX: )
Реализуем класс для универсальной загрузки XML. Будем читать данные комфортными порциями и мапить их на произвольные объекты. Класс объекта передаем в загрузчик.
Структура справочника состоит из нескольких типов XML-файлов. Для каждой создадим таблицу в БД, опишим сущности. Пример для адресных объектов:
Читаем нашим XML загрузчиком адреса пачками в структуру GarAddressobject и тут же производим сохранение в БД.
Для файлов домов, муниципальных образований и пр. алгоритм такой же, полный код загрузчика по ссылке
В итоге имеем:
- Регламентная загрузка ГАР перестала падать изза нехватки памяти
- Можно управлять кол-вом строк, которые за раз вычитывает XML-загрузчик
- Сам загрузчик довольно универсальный, его можно переиспользовать в других задачах
- Понимаем отличия в подходах DOM и SAX. Знаем где какой вариант лучше подойдет: )
Зарегался здесь, чтобы сказать огромное спасибо автору!) Очень актуальная и полезная инфа для меня, задавался вопросом как работать с такими объёмами, но ещё не начал реализовывать и тут так кстати пришлась эта статья.
Надеюсь на чудо, что автор ответит, и спрошу, как в системе ГАР связываются данные в файлах между собой? Я никак не могу найти внятной документации. Есть дом, как он привязывается к улице? Как улица к населенному пункту и т.д.? Буду благодарен за ответ или за ссылку на доку, если она всё таки есть
Добрый день! Извините что долго не отвечал, только увидел комментарий)
К сожалению по связям таблиц ГАР у меня нет информации.
Задача стояла загрузить как есть - каждый XML в отдельную таблицу в БД. Дальше уже спецы по базам делают свою магию с этими данными)
Зарегался здесь, чтобы сказать огромное спасибо автору!) Очень актуальная и полезная инфа для меня, задавался вопросом как работать с такими объёмами, но ещё не начал реализовывать и тут так кстати пришлась эта статья.
Надеюсь на чудо, что автор ответит, и спрошу, как в системе ГАР связываются данные в файлах между собой? Я никак не могу найти внятной документации. Есть дом, как он привязывается к улице? Как улица к населенному пункту и т.д.? Буду благодарен за ответ или за ссылку на доку, если она всё таки есть
Добрый день! Извините что долго не отвечал, только увидел комментарий)
К сожалению по связям таблиц ГАР у меня нет информации.
Задача стояла загрузить как есть - каждый XML в отдельную таблицу в БД. Дальше уже спецы по базам делают свою магию с этими данными)
Большое спасибо за положительный отзыв!)