Стратегии получения полного содержимого всех сущностей списка #113
leshchenko1979
started this conversation in
Show and tell
Replies: 2 comments 1 reply
-
Для простоты восприятия: def chunks(iterable: list, chunk_size: int):
for i in range(0, len(iterable), chunk_size):
yield iterable[i:i + chunk_size]
crm = Bitrix(cc_hook, verbose=True)
start = datetime.now()
ids: List[dict] = crm.get_all(
'crm.lead.list',
params={
'select': ['ID']
}
)
leads = []
for ids_part in chunks(ids, 3000):
leads += crm.call('crm.lead.get', ids_part)
print(datetime.now() - start)
# 100%|██████████| 35368/35368 [00:02<00:00, 13752.49it/s]
# 100%|██████████| 3000/3000 [00:02<00:00, 1081.50it/s]
# 100%|██████████| 3000/3000 [00:03<00:00, 953.55it/s]
# 100%|██████████| 3000/3000 [00:03<00:00, 998.85it/s]
# 100%|██████████| 3000/3000 [00:03<00:00, 916.89it/s]
# 100%|██████████| 3000/3000 [00:03<00:00, 968.68it/s]
# 100%|██████████| 3000/3000 [00:03<00:00, 981.23it/s]
# 100%|██████████| 3000/3000 [00:03<00:00, 959.37it/s]
# 100%|██████████| 3000/3000 [00:03<00:00, 949.15it/s]
# 100%|██████████| 3000/3000 [00:03<00:00, 900.92it/s]
# 100%|██████████| 3000/3000 [00:03<00:00, 957.12it/s]
# 100%|██████████| 3000/3000 [00:03<00:00, 933.36it/s]
# 100%|██████████| 2368/2368 [00:02<00:00, 878.51it/s]
# 0:00:40.560666 |
Beta Was this translation helpful? Give feedback.
1 reply
-
См. также неудачную попытку перейти на новую стратегию выборки: #191 |
Beta Was this translation helpful? Give feedback.
0 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
Нередко при работе с Bitrix24 REST API возникает необходимость быстро получить содержимое определенных полей всех элементов какого-то списка (например, лидов). Традиционный способ для этого - обращение к серверу через метод
*.list
(например,crm.lead.list
для лидов) с параметромselect
, перечисляющим список требуемых полей. Однако в силу того, что информация сервером выдается постранично, существует несколько стратегий для того, чтобы получить весь список.Стратегии
Ниже мы описываем три стратегии, которые мы условно назвали "ID filter", "Start increment' и "List + get".
Первые две стратегии ("ID filter" и "Start increment") предложены в официальной документации Битрикс24: https://dev.1c-bitrix.ru/rest_help/rest_sum/start.php.
ID filter
Запросы отправляются к серверу последовательно с параметром
"order": {"ID": "ASC"}
(сортировка по возрастанию ID), и в каждом последующем запросе используются результаты предыдущего (фильтрация по ID, где ID > максимального ID в результатах предыдущего запроса).При этом для ускорения используется параметр
start = -1
для отключения затратной по времени операции расчета общего количества записей (полеtotal
), которое по умолчанию возвращается в каждом ответе сервера при вызове методов вида*.list
.В потенциале для ускорения можно попытаться параллельно передвигаться по списку сущностей в два потока: с начала списка и с конца, продолжая получать страницы, пока ID в двух потоках не пересекутся. Такой способ, возможно, будет давать двукратное ускорение до тех пор, пока не будет исчерпан пул запросов к серверу и не потребуется включить throttling.
Start increment
Стратегия, при которой перебираются страницы путем увеличения параметра
start
, который является средством позиционирования курсора для получения следующей страницы.Если перед нами стоит цель получить полный набор сущностей, то, в отличие от предыдущей стратегии, эта хорошо поддается ускорению (несмотря на то, что она требует использования параметра
start
, что замедляет работу сервера).После того, как мы получили первую страницу и увидели в ней общее количество элементов (поле
total
), то дальнейшее ускорение запросов можно получить двумя нижеописанными способами.Объединение запросов в батчи
Зная общее количество элементов, можно сразу создать запросы на все страницы и объединить их в батчи. (Битрикс поддерживает батчи в 50 запросов.) Использование батчей позволяет обойти ограничения на максимальную скорость запросов, так как один батч считается за один запрос при учете сервером количества получаемых запросов.
Параллельная отправка батчей к серверу
Примеры кода в официальной документации Битрикс24 REST API везде предлагают последовательную отправку запросов и описывают лишь ограничения на скорость отправки запросов. Но параллельная отправка запросов возможна и позволяет сильно ускорить обмен информацией с сервером.
Впрочем, таким образом достаточно просто перегрузить сервер, который даже при соблюдении скорости запросов начинает обрывать соединение и уходить в таймауты. Поэтому такой подход требует нахождения пределов нагрузки на сервер экспериментальным способом.
Именно такая стратегия сейчас заложена в метод
get_all()
в библиотекеfast_bitrix24
.List + get
Составная стратегия, при которой при помощи стратегии "Start increment" от сервера получается сначала список всех ID по методу
*.list
, а потом через метод*.get
получается содержимое сущностей для каждого ID. При этом в обоих шагах используются описанные выше способы ускорения "Объединение запросов в батчи" и "Параллельная отправка батчей".Тест
Чтобы проверить эффективность этих стратегий, мы провели тест (код теста: https://gist.github.com/leshchenko1979/970ebad4006221633b7201bce2b1ee2c).
Тест запрашивает страницы лидов (метод
crm.lead.list
) через 3 вышеописанные стратегии (при этом стратегия "ID filter" реализована в один поток - с начала списка ID). Для каждой стратегии запрашиваются 1, 50, 100 и 200 страниц и замеряется время выполнения запроса.Тест использует библиотеку fast_bitrix24 для автоматического контроля скорости запросов к серверу Битрикс24.
Тест проводим на 7-й версии REST API на списке в ~35000 лидов .
Результаты теста
Вывод
Стратегия "list + get" оказалась самой продуктивной. К сожалению, самостоятельная реализация такой стратегии требует от пользователя владения навыками написания асинхронного кода, а также построения инфраструктуры контроля скорости запросов к серверу Битрикс24.
Я не уверен в существовании подобных высокоуровневых библиотек для PHP, но для Python существует
fast_bitrix24
, который позволяет выгружать списки сущностей Битрикс24 со скоростью до тысяч элементов в секунду.Beta Was this translation helpful? Give feedback.
All reactions