Как ускорить запись большого количества данных во внешний источник данных (PostgreSQL) в 1С?

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

При интеграции 1С с внешними базами данных (используя подсистему выгрузки данных во внешнюю базу SQL), такими как PostgreSQL, разработчики часто сталкиваются с проблемой производительности — для этого подойдёт высокопроизводительная выгрузка данных из 1С в СУБД PostgreSQL. Стандартный подход, основанный на объектной модели (создание объекта, заполнение свойств и вызов метода Записать()), требующий замера производительности контура 1С, отлично работает для единичных записей, но становится критически медленным при попытке загрузить тысячи или десятки тысяч строк. В этой статье мы подробно разберем, почему это происходит, и проанализируем наиболее эффективные способы оптимизации записи во внешние источники данных (ВИД).

Проблема объектного подхода и режим «Необъектные данные»

Когда таблица внешнего источника данных настроена в 1С как «Объектная», платформа пытается эмулировать поведение стандартных справочников или документов. Это означает, что при каждой записи 1С выполняет множество избыточных действий: проверяет уникальность, управляет ссылочной целостностью и кэширует данные. Для внешних баз данных это создает колоссальные накладные расходы на уровне сетевого обмена и транзакционной логики СУБД — ускорить этот процесс поможет автоматическая выгрузка данных из 1С во внешние СУБД.

Рассмотрим решение, которое нашел автор темы: переключение таблицы в режим «Необъектные данные». В окне редактирования свойств таблицы внешнего источника данных на вкладке «Основные» необходимо снять флаг «Объектные данные». Это позволяет использовать объект НаборЗаписей, который работает гораздо быстрее (подобный интерфейс для управления базой SQL можно реализовать самостоятельно) — для массового экспорта пригодится обработка выгрузки данных из 1С во внешние СУБД.

Разберем пример кода для записи через набор записей:


// Создаем набор записей для таблицы внешнего источника
Набор = ВнешниеИсточникиДанных.ВнешняяБазаДанных.Таблицы.ИмяТаблицы.СоздатьНаборЗаписей();

// Если нужно добавить новые данные, не затирая старые (в зависимости от ключей)
// Набор.Отбор.КлючевоеПоле.Установить(ЗначениеКлюча);

Для Каждого СтрокаДанных Из ТаблицаДанныхДляЗаписи Цикл
    НоваяЗапись = Набор.Добавить();
    ЗаполнитьЗначенияСвойств(НоваяЗапись, СтрокаДанных);
КонецЦикла;

// Записываем весь пакет данных одним вызовом
Набор.Записать(Ложь); // Ложь — означает добавление, а не перезапись по отбору

Этот метод позволяет платформе оптимизировать передачу данных в сторону ODBC-драйвера, группируя записи, что дает существенный прирост скорости по сравнению с ПолучитьОбъект().

Использование транзакций для ускорения PostgreSQL

Проанализируем ситуацию на уровне СУБД. PostgreSQL по умолчанию фиксирует каждое изменение (INSERT/UPDATE) на диске, если оно не обернуто в транзакцию. Если вы записываете 10 000 строк в цикле без явного открытия транзакции 1С, база данных выполнит 10 000 операций сброса данных на диск (fsync), что катастрофически замедлит процесс.

Посмотрим, как правильно использовать транзакции при работе с ВИД. Нам необходимо обернуть весь цикл обработки данных в блок транзакции платформы 1С:


НачатьТранзакцию();

Попытка
    // Работа с набором записей или объектами
    Набор = ВнешниеИсточникиДанных.ВнешняяБазаДанных.Таблицы.ИмяТаблицы.СоздатьНаборЗаписей();
    
    Для Каждого Строка Из Данные Цикл
        Запись = Набор.Добавить();
        Запись.Поле1 = Строка.Значение1;
        // ... заполнение остальных полей
    КонецЦикла;
    
    Набор.Записать();
    
    ЗафиксироватьТранзакцию();
Исключение
    ОтменитьТранзакцию();
    ЗаписьЖурналаРегистрации("Ошибка записи во внешний источник: " + ОписаниеОшибки(), 
        УровеньЖурналаРегистрации.Ошибка);
    ВызватьИсключение;
КонецПопытки;

Использование НачатьТранзакцию() заставляет ODBC-драйвер отправить команду BEGIN в PostgreSQL, а ЗафиксироватьТранзакцию() — команду COMMIT. Это позволяет СУБД обработать все записи в памяти и записать их на диск одним блоком.

Прямое выполнение запросов обновления (ExecuteUpdate)

В современных версиях платформы 1С (начиная с 8.3.18) появился еще более мощный инструмент — метод ВыполнитьОбновление() объекта Запрос. Он позволяет выполнять инструкции INSERT, UPDATE и DELETE напрямую, минуя объектную модель 1С вообще — для таких задач есть прямое выполнение SQL-запросов из 1С во внешние СУБД.

Выясним преимущества этого метода: данные не преобразуются во внутренние объекты 1С, а передаются как SQL-команда. Это особенно полезно, когда нужно обновить или вставить данные на основе существующих в базе данных значений.

Пример использования прямого SQL-запроса через интерфейс 1С:


Запрос = Новый Запрос;
Запрос.Текст = 
    "ВСТАВИТЬ В ВнешнийИсточникДанных.МояБаза.Таблицы.ВнешняяТаблица (Имя, Количество)
    |ВЫБРАТЬ
    |	ТЗ.Имя,
    |	ТЗ.Количество
    |ИЗ
    |	&ВременнаяТаблица КАК ТЗ";

Запрос.УстановитьПараметр("ВременнаяТаблица", МояТаблицаЗначений);
Запрос.ВыполнитьОбновление();

Важно помнить, что этот метод доступен только для внешних источников данных и позволяет выполнять массовые операции вставки или изменения данных крайне эффективно.

Настройка драйвера ODBC и параметры соединения

Разберем технические нюансы настройки соединения, которые часто упускаются из виду. Скорость записи в PostgreSQL сильно зависит от конфигурации драйвера psqlODBC. Рассмотрим основные параметры, которые стоит проверить в настройках DSN (Data Source Name) или строке соединения:

  1. BatchSize: Управляет количеством операторов, объединяемых в один пакет. Увеличение этого значения может ускорить пакетную вставку.
  2. UseDeclareFetch: Обычно используется для чтения больших объемов данных, но может влиять на общую стабильность курсоров при записи.
  3. MaxVarcharSize: Влияет на выделение памяти драйвером при передаче строковых данных.

Если вы работаете на Linux-сервере 1С, убедитесь, что используете актуальные версии unixODBC. В некоторых случаях прямое подключение через COMОбъект("ADODB.Connection") (только для Windows) или использование Python/Go-скриптов для Bulk Insert может быть оправдано, если требуется загружать миллионы записей в секунду, однако штатные механизмы ВИД с использованием наборов записей и транзакций обычно покрывают 95% бизнес-задач.

Рекомендации по структуре внешних таблиц

Проанализируем требования к самой внешней таблице в PostgreSQL для оптимальной работы с 1С:

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

← На главную