gubin_niko
@gubin_niko

Как ускорить сравнение больших массивов?

Добрый день. Есть фоновый скрипт, который обрабатывает около миллиона объектов за проход (в несколько потоков и т.д., но не в этом суть).

Есть массивы объектов obj_1 и obj_2. По структуре они одинаковые, разное только наполнение.
Ниже примерный код, которым они сравниваются:
foreach ($obj_1 as $item_1) {
    $minus = [];

    // Перебираем каждый элемент со всем массивом obj_2
    foreach ($obj_2 as $item_2) {
      // Тут мы сравниваем не большие вложенные массивы, размером от 1 до 8 записей (слова)
      $diff = array_diff($item_2->parts, $item_1->parts);

      // Исключение должно быть одно, если оно есть, то пишем в отдельный массив
      if (count($diff) == 1) {
        $diff = current($diff);
        $minus[$diff] = $diff;
      }
    }

    // Что-то делаем с $minus, но не об этом разговор
  }


Сценарий работает, вполне, но т.к. объём данных увеличился резко, он работает очень долго, и я хотел бы узнать у более грамотных людей, можно ли как то оптимизировать этот участок и сэкономить дорогое время? Понимаю, что может из php не получится выжать больших результатов, но если это как-то можно улучшить, то буду очень благодарен за помощь.

К примеру в моём случае сравниваются (один из кусочков всего алгоритма) примерно 450 (в parts 1 элемент всего) записей с 123000 (в parts 2 элемента) и это занимает 25 секунд в среднем (работает в 2 потока). После 123000 будут сравниваться со след.группой, возможно там даже больше записей будет, и посчитав мы получаем уже два-три часа, а впереди ещё пара групп таких жирных, и в итоге получается 12-16 часов работа сценария, если и не больше (а может и меньше).

Если для предложения идей не хватает моих данных, готов исправиться и дополнить. Мне нужна ваша помощь, коллеги))

P.S. Количество потоков увеличивать не предлагайте - кладёт CPU на лопатки. Может выделят более мощный сервер с парочкой камней, но пока приходится не рассчитывать на процессор.
  • Вопрос задан
  • 359 просмотров
Пригласить эксперта
Ответы на вопрос 2
Надо смотреть что за слова там. Вы ищете вхождение слова в фразу или какое конкретно совпадение он ищет? В зависимости от этого можно придумать предварительный алгоритм уменьшения операций.
Ответ написан
ThunderCat
@ThunderCat Куратор тега PHP
{PHP, MySql, HTML, JS, CSS} developer
первое что бросается в глаза:
// Исключение должно быть одно, если оно есть, то пишем в отдельный массив
if (count($diff) == 1) {
$diff = current($diff);
$minus[$diff] = $diff;
}

break если нужно всего 1 совпадение, или я не вник в задачу....
остальное - как всегда - дъявол кроется в деталях

UPD: если все эти прыжки с бубном тянутся из бд - нужно постараться сократить выборку на уровне селектов, возможно даже сделать выборки из базы по более притянутым критериям и получить больше запросов, при меньшей работе с массивами, все таки бд изначально быстрее работают с сортировками и выборками/сравнениями. Для текстовых полей включить фултекст серч для быстрой выборки - и вперед.
Ответ написан
Ваш ответ на вопрос

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

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