Получить большие объемы данных

Часто встает задача импорта каких либо сущностей с портала посредством 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
            )
        )
        
Следующая