При пакетной загрузке больших объемов данных в 1С (от сотен тысяч записей) разработчики часто сталкиваются с прогрессирующим замедлением: первые порции данных записываются за доли секунды, но по мере роста объема время фиксации каждой следующей пачки увеличивается в разы. В итоге процесс может растянуться с нескольких минут до нескольких часов, при этом диск загружен на 100%, а фактическая линейная скорость записи составляет всего пару мегабайт в секунду. Разберем детально, почему возникает эта проблема и как кардинально ускорить запись проводок в регистр бухгалтерии.
Проанализируем механику работы платформы «1С:Предприятие» и СУБД при работе с регистром бухгалтерии. В отличие от простых регистров сведений, регистр бухгалтерии обладает сложной архитектурой:
ASYNC_IO_COMPLETION.Самый действенный способ ускорить массовую вставку проводок — временно отключить пересчет итогов. Для этого у менеджера регистра бухгалтерии предусмотрен специальный метод УстановитьИспользованиеИтогов(). После завершения загрузки использование итогов включается обратно, и платформа выполняет единовременный фоновый пересчет только для тех периодов, в которых появились новые движения.
Посмотрим на пример правильной организации кода при массовой загрузке:
// Отключаем пересчет итогов перед началом загрузки
РегистрыБухгалтерии.Хозрасчетный.УстановитьИспользованиеИтогов(Ложь);
РегистрыБухгалтерии.Хозрасчетный.УстановитьИспользованиеТекущихИтогов(Ложь);
Попытка
// Выполняем массовое создание документов и запись проводок
ЗагрузитьДанныеИзФайлов();
// Включаем итоги обратно после завершения загрузки
РегистрыБухгалтерии.Хозрасчетный.УстановитьИспользованиеИтогов(Истина);
РегистрыБухгалтерии.Хозрасчетный.УстановитьИспользованиеТекущихИтогов(Истина);
Исключение
// Гарантированно восстанавливаем работу итогов в случае ошибок
РегистрыБухгалтерии.Хозрасчетный.УстановитьИспользованиеИтогов(Истина);
РегистрыБухгалтерии.Хозрасчетный.УстановитьИспользованиеТекущихИтогов(Истина);
ВызватьИсключение;
КонецПопытки;
Если записи загружаются за старые исторические периоды, дополнительно рекомендуется сдвинуть дату расчета итогов назад с помощью метода УстановитьПериодРассчитанныхИтогов(), чтобы исключить накладные расходы на актуализацию последующих месяцев.
При пакетной загрузке важно отключить платформенные проверки, подписки на события и механизмы регистрации изменений для планов обмена. Рассмотрим ключевые параметры, которые необходимо взводить перед записью объектов и наборов:
// Отключение прикладных обработчиков и проверок
НаборЗаписей.ОбменДанными.Загрузка = Истина;
ДокументОбъект.ОбменДанными.Загрузка = Истина;
// Отключение регистрации изменений в планах обмена (РИБ)
НаборЗаписей.ОбменДанными.Получатели.АвтоЗаполнение = Ложь;
ДокументОбъект.ОбменДанными.Получатели.АвтоЗаполнение = Ложь;
Также обратим внимание на архитектуру формирования документов-регистраторов:
Запись каждого документа порождает отдельную дисковую операцию сброса лога транзакций СУБД (WRITELOG). Объединение записи нескольких документов в одну общую транзакцию снижает нагрузку на дисковую подсистему в десятки раз.
Разберем по шагам реализацию порционной фиксации транзакций:
Счетчик = 0;
РазмерПорции = 100; // Фиксируем по 100 документов в одной транзакции
НачатьТранзакцию();
Для Каждого ДанныеДокумента Из МассивЗагрузки Цикл
// Создание и запись документа с движениями
ЗаписатьДокументОперация(ДанныеДокумента);
Счетчик = Счетчик + 1;
Если Счетчик % РазмерПорции = 0 Тогда
ЗафиксироватьТранзакцию();
НачатьТранзакцию();
КонецЕсли;
КонецЦикла;
Если Счетчик % РазмерПорции <> 0 Тогда
ЗафиксироватьТранзакцию();
КонецЕсли;
Если в процессе интенсивной вставки деградация скорости все же наступила, причиной является критическая фрагментация индексов таблицы движений и аналитики. Стандартные планы обслуживания могут пропускать таблицы, если статистика фрагментации еще не обновилась.
Для устранения задержек применимы следующие шаги:
REBUILD INDEX) для таблиц движений регистра бухгалтерии (соответствующие таблицы в SQL имеют префикс _AccReg и _AccRegED). Это восстанавливает непрерывность страниц данных и снижает дисковые очереди.SE_MANAGE_VOLUME_NAME). Без этого при каждом автоувеличении файла базы данных (MDF) СУБД заполняет новое пространство нулями, полностью замораживая процесс записи.