Как ускорить перенос и актуализацию регистра сведений в Конвертации данных 2.1?

Программист 1С v8.3 (Обычные формы) IT и автоматизация бизнеса
← На главную

При передаче регистра сведений из информационной базы источника в приемник через «Конвертацию данных 2.1» разработчики часто сталкиваются с падением производительности. Ситуация усложняется, если в источнике регистр является периодическим независимым, а в приемнике — непериодическим, и при каждом обмене требуется поддерживать в целевой базе актуальный срез последних. Рассмотрим подробнее, почему возникают задержки, и разберем эффективные способы оптимизации этой задачи.

Причины низкой производительности при стандартном обмене

Выясним причину, почему стандартная схема работы правила выгрузки данных (ПВД) и правил очистки данных (ПОД) может выполняться по несколько минут даже на небольших объемах данных (15–20 тысяч записей):

  1. Стандартное правило очистки данных (ПОД): Механизм ПОД удаляет записи в приемнике поэлементно или небольшими порциями. Это вызывает регулярный пересчет индексов таблицы СУБД и вызов платформенных обработчиков событий, из-за чего очистка 16 000 записей может затягиваться на 5 минут и более.
  2. Ошибки конфигурации ПВД при произвольном алгоритме: Если в ПВД выбран произвольный алгоритм и переопределена переменная ВыборкаДанных, но не указан ОбъектВыборки, платформенные обработки обмена выдают ошибку вида Несоответствие типов (параметр номер '1') при вызове метода НайтиПоТипу.
  3. Избыточная полная выгрузка: Выгрузка всего среза последних при каждом сеансе обмена сводит на нет преимущества планов обмена, создавая нагрузку на сеть, оперативную память и СУБД.

Способ 1. Быстрая очистка регистра в приемнике через набор записей

Если специфика задачи действительно требует полной перезаписи всего регистра в приемнике при каждом обмене, откажемся от ПОД в пользу прямого очищения таблицы СУБД. Для этого выполним очистку на стороне приемника в глобальном обработчике правил конвертации.

Разберем по шагам настройку быстрой очистки:

  1. Отключим или удалим стандартные правила очистки данных (ПОД) для этого регистра.
  2. В Конвертации данных перейдем в правила конвертации и открываем обработчик события ПередЗагрузкойДанных.
  3. Пропишем программное создание и запись пустого набора записей:

НаборЗаписей = РегистрыСведений.ИмяРегистраПриемника.СоздатьНаборЗаписей();
НаборЗаписей.Записать(Истина);

Запись пустого набора записей без установки отбора выполняет очистку таблицы на стороне базы данных единой быстрой операцией. Это занимает меньше одной секунды вместо нескольких минут при стандартном ПОД.

Способ 2. Организация инкрементального обмена через планы обмена

Чтобы не переносить весь объем данных (16 000 записей) при каждом обмене, настроим выгрузку среза последних только по тем объектам, изменения которых зарегистрированы на узле плана обмена.

Проанализируем ситуацию: в ПВД в обработчике ПередОбработкой напишем запрос, который связывает таблицу изменений плана обмена с виртуальной таблицей среза последних регистра-источника.

Посмотрим на пример запроса для заполнения ВыборкаДанных:


Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |	Изменения.Ссылка КАК Номенклатура,
    |	Срез.Сегмент КАК Сегмент
    |ИЗ
    |	РегистрСведений.СегментыНоменклатуры.Изменения(ПланОбмена) КАК Изменения
    |	ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.СегментыНоменклатуры.СрезПоследних(&Период, ) КАК Срез
    |		ПО Изменения.Ссылка = Срез.Номенклатура";

Запрос.УстановитьПараметр("Период", ТекущаяДата());
Запрос.УстановитьПараметр("ПланОбмена", УзелОбмена);

ВыборкаДанных = Запрос.Выполнить().Выгрузить();

После успешной выгрузки зарегистрированные изменения снимаются с узла плана обмена стандартным образом, что снижает объем передаваемых данных в сотни раз.

Способ 3. Обработка удаления записей в приемнике (сценарий «БезСегмента»)

Рассмотрим случай, когда в источнике номенклатуру перевели в специальное состояние (например, значение измеряемого свойства стало «БезСегмента»), и соответствующую запись в непериодическом регистре приемника требуется не обновить, а полностью удалить.

При использовании инкрементального обмена организуем удаление конкретной записи через ПКО регистра сведений:

  1. В ПКО регистра сведений переходим в обработчик ПередЗагрузкой.
  2. Проверяем входящее значение сегмента. Если передано пустое значение или значение «БезСегмента», программно удаляем существующую запись из регистра приемника по ключу и отменяем стандартное проведение записи КД.

Проанализируем код обработчика ПередЗагрузкой в ПКО:


ЗначениеСегмента = ОбъектАналог.Сегмент; // или данные из входящего источника

Если НЕ ЗначенияЗаполнены(ЗначениеСегмента) Или ЗначениеСегмента = Справочники.СегментыНоменклатуры.БезСегмента Тогда
    
    // Удаляем существующую запись из непериодического регистра приемника
    Набор = РегистрыСведений.ИмяРегистраПриемника.СоздатьНаборЗаписей();
    Набор.Отбор.Номенклатура.Установить(Источник.Номенклатура);
    Набор.Записать(Истина); // Запись пустого набора с отбором удаляет запись
    
    // Отменяем стандартное создание/обновление записи ПКО
    Отказ = Истина;
    
КонецЕсли;

Способ 4. Перенос данных через таблицу значений в параметрах

Если сопоставление полей в ПКО работает медленно из-за большого числа ссылочных объектов, применим альтернативный подход без использования стандартного механизмов сопоставления КД для каждой строки регистра:

  1. В ПВД в событии ПередОбработкой формируем запрос к срезу последних регистра-источника и выгружаем результат в Таблицу Значений.
  2. Помещаем подготовленную таблицу в коллекцию Параметры.
  3. В обработчике ПослеЗагрузкиДанных на стороне приемника считываем таблицу из параметров и напрямую записываем данные в регистр через СоздатьНаборЗаписей().

Этот способ полностью обходит накладные расходы платформы на пообъектную конвертацию правил и ускоряет загрузку данных в несколько раз.

← На главную