Рано или поздно любой системный администратор или разработчик 1С сталкивается с задачей пакетного перепроведения документов за длительный период. Ситуация стандартная: программист запускает процедуру на ночь, за 5 часов перепроводится около 15 500 документов (в среднем от 0.86 до 1.16 секунды на один документ), а руководство выражает крайнее недовольство скоростью работы системы. Бизнесу нужно быстрее, и кивать на то, что «одна секунда на документ — это норма», не получится.
В этой статье мы подробно разберем, почему стандартные механизмы 1С могут работать медленно, и рассмотрим комплексный подход к оптимизации этого процесса. Мы пройдемся по всем уровням: от настройки серверного оборудования и СУБД до тонких программных манипуляций в коде конфигурации.
Проанализируем конфигурацию сервера, которая часто встречается в подобных задачах. Например, двухпроцессорный Dell R710 с процессорами Intel Xeon X5650 (частота 2.67 ГГц) и быстрым дисковым массивом RAID 10 на SSD SAS. На первый взгляд, мощное серверное железо. Однако при перепроведении документов загрузка процессора и дисков может не превышать 10–15%. Выясним причину этого поведения.
Процесс проведения одного документа в 1С — это строго последовательная однопоточная задача. Платформа не умеет распределять проведение одного конкретного документа на несколько ядер процессора. В результате вся нагрузка ложится на одно активное ядро. Процессор Nehalem/Westmere разработки 2010 года с частотой 2.67 ГГц в однопоточном режиме показывает крайне низкую производительность по сравнению с современными решениями.
Для ускорения работы на аппаратном уровне выполним следующие действия:
High Performance (максимальная производительность). По умолчанию операционная система и процессор часто сбрасывают частоты неиспользуемых ядер, что создает микрозадержки при переключении потоков 1С.Если сервер СУБД и сервер приложений 1С работают на одной физической машине, неправильные настройки их взаимодействия могут свести на нет преимущества быстрых SSD-дисков. Разберем по шагам ключевые настройки СУБД, которые помогут кардинально ускорить пакетную запись данных.
Включаем протокол Shared Memory (Общая память). Если СУБД и сервер 1С находятся на одном хосте, их взаимодействие должно происходить не через сетевой протокол TCP/IP, а через общую память. Это исключает сетевые задержки операционной системы на передачу пакетов между процессами rphost и sqlservr.
Переводим базу данных в простую модель восстановления (Simple Recovery Model). Перед началом длительного перепроведения документов временно переключим модель восстановления базы данных с Full на Simple. Это существенно снизит объем транзакционных логов, записываемых на диск в файл .ldf, так как СУБД не будет сохранять избыточную информацию для резервного копирования «по точкам во времени». После окончания процесса вернем модель Full и сразу сделаем полный бэкап базы.
Настраиваем TempDB и автоприрост файлов. Временная база данных СУБД (TempDB) активно используется 1С для построения виртуальных таблиц при проведении документов. Выполним следующие настройки:
TempDB на несколько файлов одинакового размера (рекомендуется количество файлов, равное числу логических ядер процессора, но не более 8).Включаем флаги трассировки MS SQL Server. Для оптимизации работы СУБД с временными таблицами 1С рекомендуется включить флаги трассировки 1117 (одновременное расширение всех файлов в группе) и 1118 (выделение полных экстентов вместо смешанных). Это существенно снизит конкуренцию за ресурсы внутри СУБД.
Перейдем к настройкам самой платформы 1С. Во время массового проведения документов система тратит колоссальные ресурсы на выполнение сопутствующих сервисных функций. Отключим их на время проведения регламентных процедур.
Монопольный режим и отключение регламентных заданий. Любая параллельная активность пользователей или фоновых процессов создает взаимные блокировки СУБД, заставляя транзакции проведения простаивать в очередях. На время ночного перепроведения переведем базу в монопольный режим, полностью отключив все фоновые и регламентные задания в консоли администрирования кластера 1С.
Отключение итогов регистров накопления и бухгалтерии. При записи движений каждого документа система производит расчет и обновление актуальных итогов по всем затронутым регистрам. Если документов много, СУБД тратит до 70% времени именно на перезапись таблиц итогов. Мы можем временно отключить итоги, провести документы и затем рассчитать их один раз в самом конце. Рассмотрим пример кода для программного управления итогами:
// Отключаем использование итогов перед началом проведения
Для Каждого Регистр Из РегистрыНакопления Цикл
Если Регистр.ПолучитьИспользованиеИтогов() Тогда
Регистр.УстановитьИспользованиеИтогов(Ложь);
КонецЕсли;
КонецЦикла;
// В этом месте выполняем процедуру группового перепроведения документов...
// Включаем использование итогов обратно и пересчитываем их
Для Каждого Регистр Из РегистрыНакопления Цикл
Регистр.УстановитьИспользованиеИтогов(Истина);
КонецЦикла;
РегистрыНакопления.ПересчитатьИтоги();
Отключение версионирования и полнотекстового поиска. В типовых конфигурациях, таких как УТ 11, включенное версионирование объектов (история данных) создает дополнительную запись в СУБД при каждом изменении документа. Временно отключим подсистемы версионирования в настройках программы. Также приостановим индексацию полнотекстового поиска через административные функции или программно.
Если оптимизация железа и СУБД не дает нужного кратного прироста скорости, к решению задачи должен подключиться программист 1С. Рассмотрим архитектурные приемы, которые позволяют обрабатывать документы в разы быстрее типовых механизмов.
Группировка транзакций (запись пакетами). По умолчанию 1С проводит каждый документ в рамках отдельной транзакции. Каждая транзакция требует физического подтверждения записи лога СУБД на диск (операция fsync), что сильно ограничивает производительность дисковой подсистемы. Объединим проведение документов в пакеты (например, по 50-100 документов) внутри одной явной транзакции:
ГраницаПакета = 100;
Счетчик = 0;
НачатьТранзакцию();
Для Каждого ДокСсылка Из МассивДокументов Цикл
Попытка
ДокументОбъект = ДокСсылка.ПолучитьОбъект();
ДокументОбъект.Записать(РежимЗаписиДокумента.Проведение);
Счетчик = Счетчик + 1;
// Каждые 100 документов фиксируем транзакцию и открываем новую
Если Счетчик % ГраницаПакета = 0 Тогда
ЗафиксироватьТранзакцию();
НачатьТранзакцию();
КонецЕсли;
Исключение
// В случае ошибки записываем лог и продолжаем работу
ЗаписатьЛогОшибок(ОписаниеОшибки());
КонецПопытки;
КонецЦикла;
Если ТранзакцияАктивна() Тогда
ЗафиксироватьТранзакцию();
EndIf;
Многопоточное распараллеливание процессов. Поскольку проведение одного документа задействует только одно ядро процессора, мы можем разделить весь массив документов на независимые группы (например, по организациям, складам или по остатку от деления внутреннего идентификатора GUID) и запустить их проведение параллельно в несколько потоков через механизм фоновых заданий платформы 1С. На многоядерном сервере это позволит загрузить процессор на полную мощность и сократить общее время выполнения задачи пропорционально количеству потоков.
Запись движений напрямую в регистры. В тех случаях, когда при перепроведении требуется лишь скорректировать аналитику или пересчитать суммы в движениях регистров, вовсе не обязательно выполнять тяжелый метод Записать(РежимЗаписиДокумента.Проведение), который инициализирует весь объект документа со всеми его проверками, подписками на события и заполнением реквизитов на форме. Гораздо быстрее рассчитать новые движения в памяти и записать их напрямую в СУБД через набор записей:
НаборЗаписей = РегистрыНакопления.ВыручкаИПродажи.СоздатьНаборЗаписей();
НаборЗаписей.Отбор.Регистратор.Установить(ДокументСсылка);
// Заполняем набор записей новыми, предварительно рассчитанными данными
НоваяСтрока = НаборЗаписей.Добавить();
НоваяСтрока.Период = ДатаДокумента;
НоваяСтрока.Номенклатура = СсылкаНоменклатура;
НоваяСтрока.СуммаВыручки = РассчитаннаяСумма;
// Записываем набор напрямую в базу данных, минуя обработчики документа
НаборЗаписей.Записать(Истина);
Для достижения максимальной скорости перепроведения документов в 1С необходима совместная работа системного администратора и разработчика. Администратор подготавливает производительную «площадку» (процессоры с высокой частотой ядра, быстрые SSD, оптимизированные настройки SQL Server и TempDB, общая память), а программист отключает избыточные проверки, группирует транзакции или распараллеливает проведение по разным рабочим процессам.