Как быстрее всего обновить товары на сайте из xml файла?

Добрый день.
Сайт на 1C-Bitrix.
Есть очень много (~80к) товаров на сайте. Поступила задача сделать обновление остатков у товаров. Остатки получаю в xml файле.
<record>
    <СкладКод><![CDATA[С00000012]]></СкладКод>
    <НоменклатураКод><![CDATA[00000006564]]></НоменклатураКод>
    <Количество><![CDATA[6]]></Количество>
</record>

В этом файле примерно 60к товаров.
Самый простой вариант, это читать этот xml (использую XMLReader), проверять остатки у товара, если остатки изменились, то перезаписывать. Примерно за час обработалось 15к позиций. Т.е. целый файл очень долго будет обрабатываться.
Есть ли какой еще вариант решения такой задачи? Было бы наверно быстрее, если как то получить только различающиеся позиции в старом и новом файле. Приходит в голову еще вариант с записью файла в таблицу, таким образом можно получить две таблицы - старая и новая. Потом через sql вывести различия и их обновлять уже. Будет ли это быстрее - пока не знаю.
  • Вопрос задан
  • 474 просмотра
Пригласить эксперта
Ответы на вопрос 1
orlov0562
@orlov0562 Куратор тега PHP
I'm cool!
Все очень зависит от того как происходит сравнение, если это вложенный цикл, что-то типа
foreach($newItems as $newItem) {
    foreach($oldItems as $oldItem) {
    }
}

то конечно это будет долго. В этой ситуации наиболее простая оптимизация, это при нахождении старой записи, удалять ее из массива, тогда чем дольше будет работать скрипт, тем меньше будет oldItems и тем больше будет скорость.
$existedItems = [...]
foreach($newItems as $newItem) {
    $oldItems = $existedItems;
    foreach($oldItems as $k=>$oldItem) {
         unset($existedItems[$k]);
    }
}


Более логичный вариант, если хватает ресурсов, это загрузить оба массива в память, для каждого из них составить составной ключ "СкладКод+НоменклатураКод" и искать элементы по нему

$newItems = [];
foreach($newItemsXml as $newItemXml) {
    $hash = $newItemXml->storeId.'::'.$newItemXml->sku; // генерим хеш
    $newItems[$hash] = $newItemXml;
}
...
// то же самое для $oldItems
...
foreach ($newItems as $hash=>$newItem) {
    $oldItem = $oldItems[$hash]; // максимально быстрая выборка
    ...
}


Если памяти не так много, тогда тот же подход но разделенный по складам, т.е. сначала один склад прогоняем, потом второй.

Если же памяти не хватает или большой расход, тогда да, загоняем в базу, можно в memory table, с индексом и перебираем уже там.
Ответ написан
Комментировать
Ваш ответ на вопрос

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

Войти через центр авторизации
Похожие вопросы