Как быстро записать 10 миллионов записей в регистр сведений 1С

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

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

В этой статье мы подробно разберем комплексный подход к решению этой задачи, объединяющий возможности платформы 1С, оптимизацию работы с СУБД и архитектурные хитрости.

Анализ проблемы: почему стандартная запись работает медленно

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

Решение 1: Параллельная запись через фоновые задания

Первое, что мы должны сделать — это задействовать всю мощь серверного оборудования. Вместо одного потока мы разделим наши 10 миллионов записей на части и запустим несколько фоновых заданий. Рассмотрим, как правильно рассчитать количество потоков. Оптимально использовать формулу: КоличествоЛогическихПроцессоров - 1, либо даже в 1.5–2 раза больше, если дисковая подсистема позволяет эффективно обрабатывать очереди записи.

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


// Определяем количество порций данных
РазмерПорции = 100000; // 100 тысяч записей на одно задание
ВсегоЗаписей = ТЗДанных.Количество();
ТекущаяПозиция = 0;
МассивЗаданий = Новый Массив;

Пока ТекущаяПозиция < ВсегоЗаписей Цикл
    КонечнаяПозиция = Мин(ТекущаяПозиция + РазмерПорции, ВсегоЗаписей);
    ПорцияДанных = ВырезатьЧастьТаблицы(ТЗДанных, ТекущаяПозиция, КонечнаяПозиция);
    
    ПараметрыЗадания = Новый Массив;
    ПараметрыЗадания.Добавить(ПорцияДанных);
    
    Задание = ФоновыеЗадания.Выполнить("ОбщийМодульСервер.ЗаписатьПорциюВРегистр", ПараметрыЗадания);
    МассивЗаданий.Добавить(Задание);
    
    ТекущаяПозиция = КонечнаяПозиция;
КонецЦикла;

ФоновыеЗадания.ОжидатьЗавершения(МассивЗаданий);

Внутри фонового задания важно использовать транзакции оптимального размера. Опытным путем установлено, что транзакции по 10 000 – 50 000 записей показывают лучшую производительность. Слишком большие транзакции перегружают tempdb и лог транзакций SQL-сервера.

Решение 2: Оптимизация на уровне платформы 1С

Проанализируем методы ускорения записи внутри самого фонового задания. Простейший и самый важный шаг — использование свойства ОбменДанными.Загрузка = Истина. Это отключает выполнение кода в подписках на события и стандартные проверки, что существенно экономит время процессора.

Посмотрим на пример эффективной записи набора данных:


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

Внимание: Если ваш регистр имеет много измерений, запись будет идти медленнее из-за сложности индексов. Если бизнес-логика позволяет, перед началом загрузки стоит отключить итоги у регистра программно через УстановитьИспользованиеИтогов(), а после завершения всех заданий — включить их обратно. Это позволит СУБД пересчитать итоги один раз для всего объема данных, а не делать это миллионы раз.

Решение 3: Низкоуровневая настройка СУБД (SQL Server)

Выясним, что можно сделать на стороне SQL-сервера, чтобы ускорить процесс. Если база работает в режиме Full Recovery Model, то при записи 10 миллионов строк файл лога транзакций (.ldf) разрастется до гигантских размеров, что может привести к остановке сервера.

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

  1. Переключить модель восстановления базы данных в Simple. Это минимизирует запись в лог.
  2. Временно удалить некластерные индексы по таблице регистра. В 1С это можно сделать, изменив структуру регистра в конфигураторе (убрав галочки «Индексировать»), либо напрямую средствами SQL (если вы понимаете риски нарушения поддержки).
  3. Убедиться, что база TempDB расположена на быстром диске (SSD/NVMe). Массовая запись активно использует временные таблицы для сортировки данных перед фиксацией.
  4. После загрузки — вернуть индексы и модель восстановления Full, а также выполнить Shrink лога, если он все же разросся.

Решение 4: Прямые SQL-запросы и Bulk Insert

Если быстродействия штатными средствами все еще недостаточно, разберем вариант с использованием прямых SQL-запросов. Это метод «вне рамок лицензионного соглашения» для критических случаев, но он обеспечивает максимальную скорость. Самый быстрый способ — это выгрузка данных из 1С во внешний CSV-файл и последующее выполнение команды BULK INSERT на стороне SQL-сервера.

Посмотрим на схему этого процесса:

  1. 1С формирует текстовый файл (CSV), где разделителем служит точка с запятой или табуляция.
  2. Вызывается ADO-соединение или внешняя утилита bcp.
  3. Данные заливаются в промежуточную (буферную) таблицу SQL.
  4. SQL-скриптом данные переносятся из буферной таблицы в основную таблицу регистра 1С с помощью конструкции INSERT INTO ... SELECT.

Такой подход позволяет записать 10 миллионов строк буквально за пару минут, так как SQL Server выполняет операцию на уровне страниц данных, минуя интерпретатор 1С.

Решение 5: Архитектурный обход — внешние базы данных

Рассмотрим ситуацию, когда 10 миллионов записей нужны только для построения отчетов. Нужно ли вообще «раздувать» основную базу 1С? Современный стек технологий предлагает использовать ClickHouse — колоночную базу данных, специально созданную для аналитики больших объемов данных.

В этом случае наши действия будут следующими:

Подведение итогов и рекомендации

Выясним краткий чек-лист для успешной записи сверхбольших объемов:

Применяя эти методы в комплексе, мы сможем сократить время записи 10 миллионов строк с нескольких часов до считанных минут, обеспечив стабильную работу системы и комфорт пользователей.

← На главную