Рассмотрим распространенную проблему производительности при интеграции 1С с внешними сайтами и сервисами via API. При массовом пересчете цен или обновлении справочников документ проведения генерирует сотни тысяч записей, которые требуется передать на сайт. Если формировать JSON-строку и производить запись в регистр сведений прямо в транзакции проведения для каждого элемента, время выполнения документа может увеличиваться с десятков минут до нескольких часов.
Проанализируем основные причины замедления работы платформы 1С:Предприятие 8.3 при массовом добавлении записей в очередь выгрузки и разберем практические способы оптимизации кода.
Разберем типичный пример кода, приводящий к критическому падению скорости при попытке сформировать очередь выгрузки:
СписокJsonСтрок = ПолучитьСписокJsonСтрокДляНабора(НаборЗаписей);
Для каждого СтрокаНабора Из СписокJsonСтрок Цикл
ДобавитьВОчередь(СтрокаНабора);
КонецЦикла;
Функция ПолучитьСписокJsonСтрокДляНабора(Набор)
СписокJsonСтрок = Новый СписокЗначений;
Для каждого СтрокаНабора Из Набор Цикл
JsonСтрока = Новый Соответствие();
JsonСтрока.Вставить("Номенклатура", ПолучитьУИДСервиса(СтрокаНабора.Номенклатура));
СписокJsonСтрок.Добавить(JsonСтрока);
КонецЦикла;
Возврат СписокJsonСтрок;
КонецФункции;
При обработке массива из сотен тысяч записей данный подход имеет ряд серьезных узких мест:
ПолучитьУИДСервиса() на каждой итерации перебора приводит к постоянным обращениям к базе данных или дополнительным вычислениям, что суммарно создает огромную задержку.Соответствие и элементы СписокЗначений. Это вызывает частую сборку мусора и высокую нагрузку на рабочий процесс rphost.Самым эффективным решением задачи является разделение оперативного проведения документа и процесса подготовки тяжелых данных для API. Разберем этот подход подробнее:
Номенклатура) или документ-основание.ЗаписьJSON и передает их во внешний сервис.Такой подходить гарантирует быстрое проведение документов пользователями, так как тяжелая логика подготовки данных переносится на фоновые процессы сервера.
Если данные необходимо готовить сразу, категорически запрещено делать запросы к СУБД внутри цикла перебора. Рассмотрим, как оптимизировать получение данных с помощью запроса:
Соответствие (где ключ — Ссылка, а значение — готовые реквизиты).При добавлении массового объема строк в регистр сведений рекомендуется применять объект НаборЗаписей с установкой флага Замещать = Ложь и производить запись порциями.
Проанализируем пример записи данных порциями по 10 000 элементов:
РазмерПорции = 10000;
Счетчик = 0;
НаборОчереди = РегистрыСведений.ОчередьВыгрузки.СоздатьНаборЗаписей();
Для каждого СтрокаИзДанных Из ТаблицаПодготовленныхДанных Цикл
ЗаписьОчереди = НаборОчереди.Добавить();
ЗаписьОчереди.Номенклатура = СтрокаИзДанных.Номенклатура;
ЗаписьОчереди.ДанныеJSON = СтрокаИзДанных.JSON;
ЗаписьОчереди.ДатаСоздания = ТекущаяДатаСеанса();
Счетчик = Счетчик + 1;
Если Счетчик % РазмерПорции = 0 Тогда
НаборОчереди.Записать(Ложь);
НаборОчереди.Очистить();
КонецЕсли;
КонецЦикла;
Если НаборОчереди.Количество() > 0 Тогда
НаборОчереди.Записать(Ложь);
НаборОчереди.Очистить();
КонецЕсли;
Использование параметра Ложь в методе Записать(Ложь) отключает предварительный поиск и удаление существующих записей регистра по отбору, переводя СУБД в режим прямого добавления строк (INSERT), что ускоряет процедуру в десятки раз.
Переиспользование одного объекта ЗаписьJSON и отказ от регулярного создания временных коллекций (таких как СписокЗначений и Соответствие) существенно разгружает оперативную память сервера приложений. Посмотрим на пример повторного использования объекта записи:
ЗаписьJSON = Новый ЗаписьJSON;
ЗаписьJSON.УстановитьСтроку();
// Запись структурированного объекта напрямую без создания лишних коллекций
ЗаписатьJSON(ЗаписьJSON, СтруктураДанных);
СтрокаРезультат = ЗаписьJSON.Закрыть();
Применение замера производительности платформы 1С вместе с оптимизацией структуры выгрузки позволяет сократить время массового формирования очереди с 3–5 часов до нескольких минут.