Найти в Дзене
Инфо-Эксперт

Как ускорить миграцию данных между Битрикс24 и другим сервисом? Случай из нашей практики

Миграция данных между разными сервисами это всегда сложный процесс. Мы разрабатываем и поддерживаем большое количество интеграций для Битрикс24 и часто сталкиваемся с подводными камнями и нештатными ситуациями, для которых приходится искать решение. Одна из самых распространенных проблем — очень медленный перенос данных или полное зависание импорта. Об одном из таких случаев мы сейчас и расскажем. Итак, клиент столкнулся с проблемой — миграция зависла на стадии импорта активити и за сутки успевала добавить в таблицу в лучшем случае 500 записей. Расширенное логирование что, что во всём виноват вот этот участок кода: $entity = Pipedrive\ActivitiesTable::getRow([
'filter' => [
'MEMBER_ID' => $this->memberId,
'PIPEDRIVE_ID' => $row['id'],
],
'select' => ['ID']
]); На его выполнение уходило чудовищное количество времени - около пяти минут. Уточнение параметров таблицы показало, что в ней отсутствует индексирование, и выборка полей по фильтру совершалась простым перебором всех записей

Миграция данных между разными сервисами это всегда сложный процесс. Мы разрабатываем и поддерживаем большое количество интеграций для Битрикс24 и часто сталкиваемся с подводными камнями и нештатными ситуациями, для которых приходится искать решение. Одна из самых распространенных проблем — очень медленный перенос данных или полное зависание импорта. Об одном из таких случаев мы сейчас и расскажем.

Итак, клиент столкнулся с проблемой — миграция зависла на стадии импорта активити и за сутки успевала добавить в таблицу в лучшем случае 500 записей. Расширенное логирование что, что во всём виноват вот этот участок кода:

$entity = Pipedrive\ActivitiesTable::getRow([
'filter' => [
'MEMBER_ID' => $this->memberId,
'PIPEDRIVE_ID' => $row['id'],
],
'select' => ['ID']
]);

На его выполнение уходило чудовищное количество времени - около пяти минут. Уточнение параметров таблицы показало, что в ней отсутствует индексирование, и выборка полей по фильтру совершалась простым перебором всех записей от первой до последней, а было их там два с половиной миллиона.

Таким образом, решение проблемы оказалось простым - единовременной индексацией таблицы SQL-командой:

CREATE INDEX activity_pipedrive_memid_pipid_x ON bx24_activities_pipedrive(MEMBER_ID, PIPEDRIVE_ID)

Важно: порядок индексации должен совпадать с порядком полей в фильтре метода getRow(). Так же перед индексацией необходимо отключить крон для текущего приложения и остановить php-процесс:

Открыть в консоли cron на редактирование командой:
sudo crontab -e -u bitrix
Посмотреть процессы на сервере:
ps aux | grep php
Убить процесс:
sudo kill -9 число_из_второй_колонки_предыдущего_вывода

Во время индексации (для таблицы весом в 3.5Gb оно, как показала практика, составляет порядка пяти минут) нельзя закрывать консоль SQL-запроса, пока не появится подтверждение об успешной операции.

После этого время запроса getRow() сократилось с пяти минут до миллисекунд, а один тик крона стал выполняться минут за десять против суток до индексации. Правда, слегка подросло время на добавление и обновление записей, поскольку на индексацию тоже тратится определённое время, но оно настолько мало, что им можно пренебречь.

Вывод — при создании миграторов необходимо индексировать таблицы по тем полям, которые используются в методе getRow() и аналогичных, у которых фильтрация происходит не по первичному ключу.