При необходимости массового проведения десятков тысяч документов (например, при переносе данных, закрытии периода или тестировании производительности) стандартный механизм ДокументОбъект.Записать(РежимЗаписиДокумента.Проведение) может выполняться крайне медленно. Выясним причину такого поведения системы и разберем практические способы, которые позволяют ускорить обработку данных в разы.
Когда система проводит документ типовым способом, на каждый документ выполняется полный цикл операций:
Если умножить этот цикл на 30 000 документов, накладные расходы на дисковый ввод-вывод и обновление итогов становятся критическими. Рассмотрим подробнее, как оптимизировать каждый этап.
Если сам документ не меняет своих реквизитов, а требуется только сформировать или обновить проводки в регистрах, можно исключить перезапись самого объекта документа. Запись набора записей регистра напрямую выполняется значительно быстрее, так как не инициирует проверку реквизитов документа и служебные подписки.
Посмотрим на пример формирования движений по регистру бухгалтерии для документа:
НаборЗаписей = РегистрыБухгалтерии.Хозрасчетный.СоздатьНаборЗаписей();
НаборЗаписей.Отбор.Регистратор.Установить(СсылкаНаДокумент);
// Заполняем проводки напрямую
Проводка = НаборЗаписей.Добавить();
Проводка.Период = ДатаДокумента;
Проводка.Регистратор = СсылкаНаДокумент;
Проводка.СчетДт = ПланыСчетов.Хозрасчетный.Товары;
Проводка.СчетКт = ПланыСчетов.Хозрасчетный.РасчетыСПоставщиками;
Проводка.Сумма = 10000;
// Записываем только движения регистра
НаборЗаписей.Записать(Истина);
Этот подход убирает лишние блокировки таблиц документов и ускоряет процесс в несколько раз.
В файловом режиме (а также в клиент-серверном) проведение каждого отдельного документа порождает собственную транзакцию с физическим сбросом данных в лог транзакций. Оборачивание обработки в явные транзакции порциями по 100–500 документов кардинально снижает нагрузку на диск.
Разберем по шагам реализацию пакетной обработки:
КоличествоВПакете = 200;
Счетчик = 0;
НачатьТранзакцию();
Пока ВыборкаДокументов.Следующий() Цикл
ДокументОбъект = ВыборкаДокументов.ПолучитьОбъект();
// Отключаем лишние проверки при программной обработке
ДокументОбъект.ОбменДанными.Загрузка = Истина;
ДокументОбъект.Записать(РежимЗаписиДокумента.Проведение);
Счетчик = Счетчик + 1;
Если Счетчик % КоличествоВПакете = 0 Тогда
ЗафиксироватьТранзакцию();
НачатьТранзакцию();
КонецЕсли;
КонецЦикла;
Если ТранзакцияАктивна() Тогда
ЗафиксироватьТранзакцию();
КонецЕсли;
При записи каждой проводки платформа обновляет таблицы итогов (например, по счетам 41 и 62). Если проводится непрерывный исторический массив данных, постоянный пересчет итогов создает основное замедление.
Проанализируем методику отключения итогов:
УстановитьИспользованиеИтогов(Ложь) или через стандартную обработку «Управление итогами».Важно: этот способ подходит, если алгоритм проведения не требует контроля остатков в реальном времени во время проведения следующего документа.
При массовой обработке данных рекомендуется отключить фоновые процессы, которые создают паразитную нагрузку:
ОбменДанными.Загрузка = Истина предотвращает запись изменений в таблицы узлов обмена.ПолнотекстовыйПоиск.УстановитьРежимУправленияРегистрацией(РежимУправленияРегистрациейПП.Запретить) исключает затраты на индексацию текстовых данных.Если проведение выполняется в файловой базе данных (.1CD), файловая система становится узким горлышком из-за блокировок таблиц целиком: