При импорте больших объемов данных в конфигурацию «1С:Бухгалтерия 3.0» разработчики часто сталкиваются с ситуацией, когда в начале процесса скорость записи составляет 200 проводок в секунду, но по мере продвижения падает до 5–9 проводок в секунду. Рассмотрим причины такого замедления и проанализируем практические способы оптимизации загрузки.
Проанализируем ситуация, с которой столкнулся автор: запись 300 000 проводок выполняется в файловой базе через документы ОперацияБух, причем один документ содержит от 10 000 до 20 000 записей. При такой архитектуре импорта возникают следующие узкие места:
.1CD): По мере увеличения общей массы записей в таблице регистра бухгалтерии размер B-tree индексов растет. Каждая новая операция записи набора требует всё больше времени на дисковые операции ввода-вывода и перестроение индексов.Для устранения узких мест и ускорения процесса записи разберем ключевые настройки программного кода.
1. Использование свойства ОбменДанными.Загрузка
Перед записью создаваемого документа и набора записей регистра бухгалтерии необходимо взводить флаг ОбменДанными.Загрузка = Истина. Это отключает выполнение тяжелых подписок на события, процедур проверок бизнес-логики и программных обработчиков конфигурации.
ДокументОбъект = Документы.ОперацияБух.СоздатьДокумент();
ДокументОбъект.ОбменДанными.Загрузка = Истина;
ДокументОбъект.Записать();
НаборЗаписей = РегистрыБухгалтерии.Хозрасчетный.СоздатьНаборЗаписей();
НаборЗаписей.Отбор.Регистратор.Установить(ДокументОбъект.Ссылка);
НаборЗаписей.ОбменДанными.Загрузка = Истина;
2. Уменьшение размера порций (дробление документов)
Не формируйте документы с 10 000–20 000 проводок. Оптимальный размер порции составляет 500–1000 проводок на один документ ОперацияБух. Маленькие наборы записей обрабатываются платформой значительно быстрее и не вызывают перегрузки оперативной памяти.
3. Прямая запись через набор записей без перечитывания документа
Выясним правильную последовательность работы с транзакцией. Не нужно удерживать одну большую транзакцию на весь файл. Объединяйте в одну транзакцию порции по 50–100 небольших документов:
НачатьТранзакцию();
Для Каждого ПорцияИз1000Записей Из ДанныеДляЗагрузки Цикл
ДокументОбъект = Документы.ОперацияБух.СоздатьДокумент();
ДокументОбъект.Дата = ТекущаяДата();
ДокументОбъект.ОбменДанными.Загрузка = Истина;
ДокументОбъект.Записать();
НаборЗаписей = РегистрыБухгалтерии.Хозрасчетный.СоздатьНаборЗаписей();
НаборЗаписей.Отбор.Регистратор.Установить(ДокументОбъект.Ссылка);
НаборЗаписей.ОбменДанными.Загрузка = Истина;
// Заполнение набора записей проводом...
НаборЗаписей.Записать();
КонецЦикла;
ЗафиксироватьТранзакцию();
4. Отключение итогов перед загрузкой
Перед началом импорта огромного массива проводок рекомендуем выключать расчет итогов регистра бухгалтерии, а после завершения — включать и выполнять пересчет. Для этого используется метод УстановитьИспользованиеИтогов():
РегистрыБухгалтерии.Хозрасчетный.УстановитьИспользованиеИтогов(Ложь);
// Выполнение загрузки проводок...
РегистрыБухгалтерии.Хозрасчетный.УстановитьИспользованиеИтогов(Истина);
РегистрыБухгалтерии.Хозрасчетный.ПересчитатьИтоги();
Посмотрим на решение задачи с точки зрения считывания XML и многопоточности. Чтение крупного XML-файла целиком через DOM-модель приводит к утечке памяти. Рекомендуется использовать объект ЧтениеXML для потокового чтения данных.
Разберем алгоритм многопоточной загрузки:
ТаблицаЗначений через объект ЧтениеXML.ТаблицаЗначений на несколько частей по количеству потоков.ФоновыеЗадания.Выполнить().Каждое фоновое задание создает свои документы ОперацияБух и записывает проводки в своем независимом сеансе. Это позволяет задействовать все ядра процессора и существенно ускорить процесс импорта.
Если загрузка проводок происходит периодически и в файловом режиме скорость остаётся неудовлетворительной, наиболее эффективным шагом станет временный перенос базы в клиент-серверный вариант (например, на PostgreSQL или MS SQL Server).
Полноценные СУБД намного эффективнее справляются с массовыми вставками (bulk inserts), оптимизируют работу с индексами и эффективно кешируют данные. После завершения импорта 300 000 проводок и пересчета итогов базу при необходимости можно выгрузить обратно в файловый формат .1CD.