Почему падает скорость при загрузке большого объема проводок в 1С и как её ускорить?

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

При импорте больших объемов данных в конфигурацию «1С:Бухгалтерия 3.0» разработчики часто сталкиваются с ситуацией, когда в начале процесса скорость записи составляет 200 проводок в секунду, но по мере продвижения падает до 5–9 проводок в секунду. Рассмотрим причины такого замедления и проанализируем практические способы оптимизации загрузки.

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

Проанализируем ситуация, с которой столкнулся автор: запись 300 000 проводок выполняется в файловой базе через документы ОперацияБух, причем один документ содержит от 10 000 до 20 000 записей. При такой архитектуре импорта возникают следующие узкие места:

  1. Рост индексов в файловой СУБД (файлы .1CD): По мере увеличения общей массы записей в таблице регистра бухгалтерии размер B-tree индексов растет. Каждая новая операция записи набора требует всё больше времени на дисковые операции ввода-вывода и перестроение индексов.
  2. Избыточный размер набора записей: Запись 10 000–20 000 проводок в рамках одного документа формирует гигантский набор записей. Это вызывает высокий расход оперативной памяти, долгую сериализацию данных и значительную нагрузку на механизмы валидации платформы.
  3. Переполнение лога транзакций и файлового кеша: Длительные транзакции с гигантскими объемами записей приводят к задержкам при синхронизации файлового кеша с диском.
  4. Архитектурные ограничения файлового режима: Файловая база 1С имеет ограничения по скорости дисковых операций и максимальному размеру одной внутренней таблицы (4 ГБ). По мере приближения к пределам падение скорости становится неизбежным.

Оптимизация работы с набором записей и объектами 1С

Для устранения узких мест и ускорения процесса записи разберем ключевые настройки программного кода.

1. Использование свойства ОбменДанными.Загрузка

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


ДокументОбъект = Документы.ОперацияБух.СоздатьДокумент();
ДокументОбъект.ОбменДанными.Загрузка = Истина;
ДокументОбъект.Записать();

НаборЗаписей = РегистрыБухгалтерии.Хозрасчетный.СоздатьНаборЗаписей();
НаборЗаписей.Отбор.Регистратор.Установить(ДокументОбъект.Ссылка);
НаборЗаписей.ОбменДанными.Загрузка = Истина;

2. Уменьшение размера порций (дробление документов)

Не формируйте документы с 10 000–20 000 проводок. Оптимальный размер порции составляет 500–1000 проводок на один документ ОперацияБух. Маленькие наборы записей обрабатываются платформой значительно быстрее и не вызывают перегрузки оперативной памяти.

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

Выясним правильную последовательность работы с транзакцией. Не нужно удерживать одну большую транзакцию на весь файл. Объединяйте в одну транзакцию порции по 50–100 небольших документов:


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

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

КонецЦикла;

ЗафиксироватьТранзакцию();

4. Отключение итогов перед загрузкой

Перед началом импорта огромного массива проводок рекомендуем выключать расчет итогов регистра бухгалтерии, а после завершения — включать и выполнять пересчет. Для этого используется метод УстановитьИспользованиеИтогов():


РегистрыБухгалтерии.Хозрасчетный.УстановитьИспользованиеИтогов(Ложь);

// Выполнение загрузки проводок...

РегистрыБухгалтерии.Хозрасчетный.УстановитьИспользованиеИтогов(Истина);
РегистрыБухгалтерии.Хозрасчетный.ПересчитатьИтоги();

Параллельная загрузка данных и потоки

Посмотрим на решение задачи с точки зрения считывания XML и многопоточности. Чтение крупного XML-файла целиком через DOM-модель приводит к утечке памяти. Рекомендуется использовать объект ЧтениеXML для потокового чтения данных.

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

  1. Считаем данные из XML-файла в порции или единую ТаблицаЗначений через объект ЧтениеXML.
  2. Разделим ТаблицаЗначений на несколько частей по количеству потоков.
  3. Запустим параллельную обработку массивов данных с использованием механизма ФоновыеЗадания.Выполнить().

Каждое фоновое задание создает свои документы ОперацияБух и записывает проводки в своем независимом сеансе. Это позволяет задействовать все ядра процессора и существенно ускорить процесс импорта.

Временный переход в клиент-серверный режим

Если загрузка проводок происходит периодически и в файловом режиме скорость остаётся неудовлетворительной, наиболее эффективным шагом станет временный перенос базы в клиент-серверный вариант (например, на PostgreSQL или MS SQL Server).

Полноценные СУБД намного эффективнее справляются с массовыми вставками (bulk inserts), оптимизируют работу с индексами и эффективно кешируют данные. После завершения импорта 300 000 проводок и пересчета итогов базу при необходимости можно выгрузить обратно в файловый формат .1CD.

← На главную