При передаче регистра сведений из информационной базы источника в приемник через «Конвертацию данных 2.1» разработчики часто сталкиваются с падением производительности. Ситуация усложняется, если в источнике регистр является периодическим независимым, а в приемнике — непериодическим, и при каждом обмене требуется поддерживать в целевой базе актуальный срез последних. Рассмотрим подробнее, почему возникают задержки, и разберем эффективные способы оптимизации этой задачи.
Выясним причину, почему стандартная схема работы правила выгрузки данных (ПВД) и правил очистки данных (ПОД) может выполняться по несколько минут даже на небольших объемах данных (15–20 тысяч записей):
ВыборкаДанных, но не указан ОбъектВыборки, платформенные обработки обмена выдают ошибку вида Несоответствие типов (параметр номер '1') при вызове метода НайтиПоТипу.Если специфика задачи действительно требует полной перезаписи всего регистра в приемнике при каждом обмене, откажемся от ПОД в пользу прямого очищения таблицы СУБД. Для этого выполним очистку на стороне приемника в глобальном обработчике правил конвертации.
Разберем по шагам настройку быстрой очистки:
ПередЗагрузкойДанных.
НаборЗаписей = РегистрыСведений.ИмяРегистраПриемника.СоздатьНаборЗаписей();
НаборЗаписей.Записать(Истина);
Запись пустого набора записей без установки отбора выполняет очистку таблицы на стороне базы данных единой быстрой операцией. Это занимает меньше одной секунды вместо нескольких минут при стандартном ПОД.
Чтобы не переносить весь объем данных (16 000 записей) при каждом обмене, настроим выгрузку среза последних только по тем объектам, изменения которых зарегистрированы на узле плана обмена.
Проанализируем ситуацию: в ПВД в обработчике ПередОбработкой напишем запрос, который связывает таблицу изменений плана обмена с виртуальной таблицей среза последних регистра-источника.
Посмотрим на пример запроса для заполнения ВыборкаДанных:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Изменения.Ссылка КАК Номенклатура,
| Срез.Сегмент КАК Сегмент
|ИЗ
| РегистрСведений.СегментыНоменклатуры.Изменения(ПланОбмена) КАК Изменения
| ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.СегментыНоменклатуры.СрезПоследних(&Период, ) КАК Срез
| ПО Изменения.Ссылка = Срез.Номенклатура";
Запрос.УстановитьПараметр("Период", ТекущаяДата());
Запрос.УстановитьПараметр("ПланОбмена", УзелОбмена);
ВыборкаДанных = Запрос.Выполнить().Выгрузить();
После успешной выгрузки зарегистрированные изменения снимаются с узла плана обмена стандартным образом, что снижает объем передаваемых данных в сотни раз.
Рассмотрим случай, когда в источнике номенклатуру перевели в специальное состояние (например, значение измеряемого свойства стало «БезСегмента»), и соответствующую запись в непериодическом регистре приемника требуется не обновить, а полностью удалить.
При использовании инкрементального обмена организуем удаление конкретной записи через ПКО регистра сведений:
ПередЗагрузкой.Проанализируем код обработчика ПередЗагрузкой в ПКО:
ЗначениеСегмента = ОбъектАналог.Сегмент; // или данные из входящего источника
Если НЕ ЗначенияЗаполнены(ЗначениеСегмента) Или ЗначениеСегмента = Справочники.СегментыНоменклатуры.БезСегмента Тогда
// Удаляем существующую запись из непериодического регистра приемника
Набор = РегистрыСведений.ИмяРегистраПриемника.СоздатьНаборЗаписей();
Набор.Отбор.Номенклатура.Установить(Источник.Номенклатура);
Набор.Записать(Истина); // Запись пустого набора с отбором удаляет запись
// Отменяем стандартное создание/обновление записи ПКО
Отказ = Истина;
КонецЕсли;
Если сопоставление полей в ПКО работает медленно из-за большого числа ссылочных объектов, применим альтернативный подход без использования стандартного механизмов сопоставления КД для каждой строки регистра:
ПередОбработкой формируем запрос к срезу последних регистра-источника и выгружаем результат в Таблицу Значений.Параметры.ПослеЗагрузкиДанных на стороне приемника считываем таблицу из параметров и напрямую записываем данные в регистр через СоздатьНаборЗаписей().Этот способ полностью обходит накладные расходы платформы на пообъектную конвертацию правил и ускоряет загрузку данных в несколько раз.