Как увеличить скорость обмена данными между базами 1С через COM-соединение?

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

Обмен данными между информационными базами 1С через COM-соединение (V83.COMConnector) часто становится «узким местом» системы. Основная проблема заключается в так называемой «болтливости» интерфейса: каждое обращение к свойству или методу объекта в другой базе через COM-границу инициирует полноценный сетевой вызов. Если таких вызовов сотни или тысячи внутри одного цикла, скорость обмена падает до неприемлемых значений. Рассмотрим детально, как мы можем оптимизировать этот процесс, начиная от исправления кода и заканчивая изменением архитектуры обмена.

Минимизация количества вызовов через COM-границу

Проанализируем типичный сценарий: программист создает объект в базе-приемнике и начинает по очереди заполнять каждый его реквизит. Каждая точка после переменной ДокументОбъект (например, Док.Дата = ..., Док.Сумма = ...) — это отдельный вызов через сеть. Если в документе 20 реквизитов и 50 строк в табличной части, количество вызовов исчисляется тысячами.

Правильное решение: Сформируем в базе-источнике структуру или массив структур, содержащий только простые типы данных (строки, числа, даты, булево). Передадим эту структуру одним вызовом в экспортную функцию базы-приемника. На стороне приемника вся логика по созданию и заполнению объекта будет выполняться локально, что в десятки раз быстрее.

Разберем пример оптимизированного подхода. Вместо прямого заполнения реквизитов в базе-источнике, подготовим данные:


// В базе-источнике
ДанныеДляПередачи = Новый Структура;
ДанныеДляПередачи.Вставить("Номер", Объект.Номер);
ДанныеДляПередачи.Вставить("Дата", Объект.Дата);
ДанныеДляПередачи.Вставить("СуммаДокумента", Объект.СуммаДокумента);
// ... заполняем остальные поля простыми типами

// Один-единственный вызов метода в базе-приемнике
Результат = COMСоединение.МойОбщийМодуль.ЗагрузитьДокумент(ДанныеДляПередачи);

Оптимизация поиска ссылочных объектов

Использование методов НайтиПоКоду() или НайтиПоНаименованию() внутри цикла заполнения данных — это еще одна критическая ошибка. Каждый такой поиск — это не только COM-вызов, но и отдельный запрос к СУБД в базе-приемнике.

Проанализируем, как сделать поиск эффективным. Нам необходимо использовать запросы. Рассмотрим алгоритм:

  1. Сберем все идентификаторы (коды или наименования) объектов, которые нужно найти, в один массив.
  2. Передадим этот массив в базу-приемник.
  3. В базе-приемнике одним запросом выберем все ссылки и поместим их в таблицу значений или соответствие.
  4. Используем полученные данные при заполнении документа.

Важный совет: Если базы синхронизированы, лучше всего использовать поиск по внутреннему идентификатору (GUID). Это самый быстрый способ. Передадим Строка(Ссылка.УникальныйИдентификатор()) и восстановим ссылку в приемнике:


// В базе-приемнике
УИД = Новый УникальныйИдентификатор(ПереданнаяСтрокаGUID);
Ссылка = Справочники.Контрагенты.ПолучитьСсылку(УИД);

Отказ от поиска предопределенных данных в коде

Часто в коде обмена встречаются конструкции вроде НайтиПоКоду("50.01") для плана счетов или НайтиПоКоду("643") для валют. Это избыточно. В базе-приемнике такие данные лучше получать через предопределенные значения или кэшированные функции общего модуля. Выясним причину: предопределенные элементы в 1С доступны напрямую по имени, и их не нужно искать в базе данных каждый раз при обмене.

Кэширование COM-соединения

Установка соединения через COMConnector.Connect() — очень дорогая операция, которая может занимать от нескольких секунд. Если мы инициируем обмен при каждом проведении документа, пользователи будут постоянно ждать. Рассмотрим варианты кэширования:

Для серверного кода (в рамках одного сеанса) можно использовать временное хранилище или параметры сеанса, чтобы не переподключаться постоянно. Однако нужно помнить, что V83.COMConnector автоматически закрывается при завершении процесса. Если требуется постоянное соединение для разных пользователей, лучше пересмотреть архитектуру в пользу регламентных заданий.

Вынос обмена из транзакции проведения

Выполнение обмена непосредственно в процедуре ОбработкаПроведения — крайне опасная практика. Если база-приемник будет недоступна или соединение «подвиснет», транзакция в базе-источнике останется открытой. Это заблокирует работу других пользователей с базой.

Рекомендуемый подход:

  1. При проведении документа делаем запись в специальный регистр сведений (ОчередьОбмена).
  2. Создаем регламентное задание, которое раз в минуту считывает данные из этого регистра и выполняет COM-подключение для передачи накопленного пакета данных.
  3. Это позволит «развязать» работу пользователей и процесс обмена, сделав систему отзывчивой.

Использование HTTP-сервисов как альтернатива COM

Если скорость по-прежнему не устраивает, проанализируем возможность перехода на HTTP-сервисы. Технология COM считается устаревшей и «тяжелой». HTTP-сервисы (REST) работают значительно быстрее, так как не требуют инициализации тяжелого окружения пользователя на стороне приемника.

Данные передаются в формате JSON. Посмотрим на примерную структуру такого обмена: База-источник формирует JSON-пакет и отправляет HTTPPOST запрос. База-приемник мгновенно принимает пакет и запускает фоновое задание по его обработке. Это избавляет от проблем с разрядностью (x64/x86) и настройкой прав DCOM.

Использование метода ЗаполнитьЗначенияСвойств

Чтобы ускорить заполнение реквизитов на стороне приемника, используем встроенную функцию ЗаполнитьЗначенияСвойств(). Она работает на уровне движка платформы и значительно быстрее ручного присваивания каждого поля.


// Пример в базе-приемнике
НовыйДок = Документы.ПриходныйКассовыйОрдер.СоздатьДокумент();
// Заполняем реквизиты с совпадающими именами из переданной структуры
ЗаполнитьЗначенияСвойств(НовыйДок, СтруктураДанных);
// Дозаполняем специфичные поля, которые требовали поиска ссылок
НовыйДок.Контрагент = НайтиНужнуюСсылку(СтруктураДанных.КонтрагентНаименование);
НовыйДок.Записать(РежимЗаписиДокумента.Проведение);

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

← На главную