Часто встает задача импорта каких либо сущностей с портала посредством rest. При этом при большом количестве сущностей прямой подход к задаче, с установкой фильтра и передачей в каждый следующий запрос start = start+50, не оптимальный. Так как, при использование start >= 0 на каждый запрос выполняется еще и запрос подсчета количества элементов удовлетворяющих фильтру. Что при большом количестве элементов, попадающих в него, или при сложной фильтрации работает медленно.
Поэтому в случае если вам не нужно количество элементов ( например вам нужно просто 10 последних записей ) или вы делаете импорт всех записей по фильтру, передавайте start = -1.
Данный параметр отключит выполнение запроса подсчета количества элементов и сильно ускорит выборку.
Для выполнения импорта, при этом необходимо будет отсортировать записи по ID и добавить в фильтр условие ID > значения последнего элемента. И с каждым шагом увеличивать его значение. Значение же последнего элемента брать из последнего значения полученного результата.
Условием остановки импорта будет пустой ответ, или то, что в ответе элементов меньше 50.
Ниже приведен пример кода и сравнение времени выполнения с классическим подходом. Так при 2 387 743 лидах, с одинаковыми правами и фильтром, время выполнения уменьшилось с 49.9 секунд до 0,097 секунд.
$tokenID = 'XXXXXXXXXXXXXXXXXXXXX';
$host = 'XXXX.bitrix24.ru';
$user = 1;
/**
* Начинаем с нуля или с какого то предыдущего шага
*/
$leadID = 0;
$finish = false;
while (!$finish)
{
/**
* Выполняем пока не заберем все данные, в этом случае не стоит забывать и про задержку между хитами.
* Либо каждый раз выбираем только 50, начиная с того элемента, на котором остановилась прошлая итерация
*/
$http = new \Bitrix\Main\Web\HttpClient();
$http->setTimeout(5);
$http->setStreamTimeout(50);
$json = $http->post(
'https://'.$host.'/rest/'.$user.'/'.$tokenID.'/crm.lead.list/',
[
'order' => ['ID' => 'ASC'],
'filter' => ['>ID' => $leadID],
'select' => ['ID', 'TITLE', 'DATE_CREATE'],
'start' => -1
]
);
$result = \Bitrix\Main\Web\Json::decode($json);
if (count($result['result']) > 0)
{
foreach ($result['result'] as $lead)
{
$leadID = $lead['ID'];
}
// Do something
}
else
{
$finish = true;
}
}
/*
//Результаты выполнения rest запроса с использованием count.
Array
(
[result] => Array
(
[0] => Array()
[1] => Array()
.....
[49] => Array()
[next] => 50
[total] => 2387743
[time] => Array
(
[start] => 1581607213.4833
[finish] => 1581607263.3997
[duration] => 49.916450023651
[processing] => 49.899916887283
[date_start] => 2020-02-13T18:20:13+03:00
[date_finish] => 2020-02-13T18:21:03+03:00
)
)
//Результаты выполнения rest запроса без использования count.
Array
(
[result] => Array
(
[0] => Array()
[1] => Array()
.....
[1] => Array()
[total] => 0
[time] => Array
(
[start] => 1581609136.3857
[finish] => 1581609136.4835
[duration] => 0.097883939743042
[processing] => 0.068500995635986
[date_start] => 2020-02-13T18:52:16+03:00
[date_finish] => 2020-02-13T18:52:16+03:00
)
)
*/