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