JaxAdam
@JaxAdam
Junior Full-Stack Developer

Как грамотно считать данные с большого XML файла?

Добрый времени суток, форумчане! Столкнулся с проблемой при интеграции товаров из 1С на сайт. Делаем мы так. Программист 1С загружает по ftp всю базу с товарами и предложениями. Файлы относительно большие 60Мб (товары) и 45Мб (предложения). Алгоритм моих действий был таков:
1) через file_get_contents брал xml файлы и считывал XML как строку в переменные;
2) полученные переменные обрабатывал функцией simplexml_load_string(<переменные из шага 1>);
3) полученные объекты превращал в массив с помощью конструкции json_decode(json_encode(<объект из шага 2>), true), именно этот пункт забирает очень много производительности по оперативке.
4) из полученного в шаге 3 массива вытягивал нужные данные циклами и передавал в модель для наполнения базы.
На предыдущих проектах, где товаров было максимум 10000 этот алгоритм работал вполне успешно. Однако в полученном сейчас проекте количество товаров составляет более 30000. При попытке совершить выгрузку, то есть выполнить вышеописанный скрипт, в данном проекте я получаю либо
Fatal error: Out of memory (allocated 137887744) (tried to allocate 20975616 bytes)
, либо ошибку 500/502/504, либо страница тупо висит и не заканчивается (пробовал ждать до 2 часов). Сайт расположен на VDS с 2Гб оперативки. Какое решение можете предложить для обработки больших XML файлов? Пока смотрю в сторону XMLReader, однако используя этот метод, ясно, что код получится полной кашой. Еще один вариант который я держу в голове: считывать два файла отдельно в разных контроллерах, записывать только нужные для себя данные в отдельный файл. А позже линковать товары и предложения по id. Помогите, пожалуйста, добрые люди!)
  • Вопрос задан
  • 253 просмотра
Решения вопроса 1
Adamos
@Adamos
Обычная проблема. Для больших файлов используется XMLReader, а не SimpleXML.
Он не пытается пережевать весь файл сразу, а читает его построчно.
Ответ написан
Пригласить эксперта
Ответы на вопрос 1
@rPman
3) полученные объекты превращал в массив с помощью конструкции json_decode(json_encode(<объект из шага 2>), true), именно этот пункт забирает очень много производительности по оперативке.
ваша проблема тут!

Зачем вы это делаете? ассоциативные массивы объективно медленнее чем работа с объектами, и даже если надо, всегда можно на конкретном уровне написать (array)$obj и работать с уже массивом полей объекта, так же foreach прекрасно работает с полями объекта как с элементами массива.

p.s. и самое главное, не работайте на сайте с xml, преобразуйте данные в более удобный для php вид, к примеру serialize или даже var_export (делает код php инициализирующий массив, его можно просто include или eval), делайте это в момент загрузки xml файла на сайте админом, а уже при работе с данными подгружайте файл удобным способом.

Ну и классика - данные нужно хранить в базе данных (загружать медленнее но зато работать быстрее всего)
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы