Документация для разработчиков
Темная тема

Как правильно выгружать большие объемы данных

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

© «Битрикс», 2001-2024, «1С-Битрикс», 2024