Все очень зависит от того как происходит сравнение, если это вложенный цикл, что-то типа
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, с индексом и перебираем уже там.