При программном заполнении и проведении документа Установка цен номенклатуры с несколькими десятками тысяч строк разработчики часто сталкиваются с существенной задержкой. При этом записи в соответствующем регистре сведений могут появляться практически сразу, но сам документ продолжает выполняться и не возвращает управление в интерфейс. Рассмотрим подробнее основные причины такого поведения платформы 1С и проанализируем эффективные способы решения этой проблемы.
Выясним причину, почему запись и проведение большого документа занимает длительное время:
Установка цен номенклатуры часто представлена иерархической структурой типа ДеревоЗначений. При наличии десятков тысяч товаров и нескольких видов цен объем данных в оперативной памяти становится огромным. Возврат управления с сервера на клиент требует длительной сериализации и передачи этой структуры.Commit) СУБД производит обновление индексов таблиц регистра сведений и документа. Хотя сторонние сеансы уже могут видеть записанные строки в регистре, основной сеанс ожидает ответа от базы данных о полном завершении транзакции.ПриЗаписи, ОбработкаПроведения), а также каскадный пересчет зависимых и динамических видов цен.Прежде чем менять алгоритм, выполним замер производительности в Отладчике. Это позволит точно определить, на какой именно строке кода или процедуре система проводит больше всего времени (запись документа, работа подписок или передача контекста на клиент).
Разберем по шагам порядок действий для диагностики:
Попытка записать 90 000 строк в один документ приводит к экспоненциальному росту нагрузки на дисковую подсистему и оперативную память. Опыт показывает, что разбиение единого массива на порции существенно сокращает суммарное время выполнения.
Посмотрим на сравнение: проведение одного документа на 90 000 строк может длиться часами из-за разрастания транзакции и объема сериализации, в то время как 9 документов по 10 000 строк (или 18 документов по 5 000 строк) обработаются суммарно значительно быстрее за счет уменьшения размеров транзакций.
Если создание документа выполняется программно (например, при первоначальном заполнении цен или импорте из внешней системы), целесообразно отключить избыточные проверки и обработчики с помощью свойства ОбменДанными.Загрузка.
Рассмотрим пример кода:
ДокументОбъект = Документы.УстановкаЦенНоменклатуры.СоздатьДокумент();
// Заполнение реквизитов и табличной части документа
// ...
ДокументОбъект.ОбменДанными.Загрузка = Истина;
ДокументОбъект.Записать(РежимЗаписиДокумента.Проведение);
Установка флага ОбменДанными.Загрузка = Истина позволяет пропустить проверки бизнес-логики и авторегистрацию в планах обмена, что значительно ускоряет проведение.
Если сохранение документов проведения не является обязательным требованием бизнес-процесса или выполняется первичная загрузка прайс-листа, наиболее эффективным решением будет отказаться от объектной техники (документа) и записать данные напрямую в регистр сведений с помощью объекта РегистрСведенийНаборЗаписей.
Проанализируем пример прямой записи набором записей:
НаборЗаписей = РегистрыСведений.ЦеныНоменклатуры.СоздатьНаборЗаписей();
НаборЗаписей.Отбор.Период.Установить(ТекущаяДата());
Для Каждого СтрИз МассиваЦен Цикл
Запись = НаборЗаписей.Добавить();
Запись.Период = ТекущаяДата();
Запись.Номенклатура = СтрИз.Номенклатура;
Запись.ВидЦены = СтрИз.ВидЦены;
Запись.Цена = СтрИз.Цена;
КонецЦикла;
НаборЗаписей.ОбменДанными.Загрузка = Истина;
НаборЗаписей.Записать(Ложь);
Прямая запись набором записей с включенным флагом Загрузка = Истина исключает накладные расходы на формирование табличных частей документов и передачу тяжелых контекстов деревьев значений между сервером и клиентом.