Проблема медленного проведения документа Табель учета рабочего времени — одна из самых «болезненных» для крупных организаций, работающих в конфигурациях «1С:Зарплата и управление персоналом» или «1С:ERP». Ситуация, когда документ проводится 50 секунд и более, вызывает справедливое недовольство пользователей и снижает общую эффективность работы системы. В этой статье мы детально разберем, как локализовать проблему, проанализируем причины задержек и рассмотрим методы оптимизации, позволяющие сократить время выполнения операции в разы.
Прежде чем приступать к оптимизации кода, нам необходимо точно выяснить, на что тратится основное время. Как правило, узкое место находится либо в вычислительной логике (подготовка данных), либо в записи движений в базу данных (метод Записать()).
Рассмотрим основные инструменты, которые мы будем использовать для анализа:
УдалитьЗаписиЗаПериодДокумента() занимает львиную долю времени — 30 секунд.DBMSSQL (или DBPOSTGRS) и SDBL. Это позволит увидеть конкретные SQL-запросы, которые выполняются при вызове метода Записать().Проанализируем ситуацию, описанную в теме: основная задержка происходит в процедуре УдалитьЗаписиЗаПериодДокумента() при вызове метода НаборЗаписей.Записать(). Рассмотрим примерный код, который может вызывать такую задержку:
Процедура УдалитьЗаписиЗаПериодДокумента()
// Создаем набор записей регистра расчета или накопления
НаборЗаписей = РегистрыРасчета.ОсновныеНачисления.СоздатьНаборЗаписей();
НаборЗаписей.Отбор.Регистратор.Установить(Ссылка);
// Попытка очистки старых движений перед новой записью
// Именно этот метод часто становится "узким местом"
НаборЗаписей.Записать();
КонецПроцедуры
Почему НаборЗаписей.Записать() может работать медленно? Выясним основные причины:
Разберем фундаментальный способ ускорения работы, который часто игнорируют программисты, пытаясь «подкрутить» код. В 1С:ЗУП 3.1 документ Табель является избыточным в 90% случаев. Система способна рассчитывать зарплату на основании графиков работы и документов-отклонений (больничные, отпуска, прогулы).
Если мы откажемся от массового ввода табелей на всех сотрудников, нагрузка на регистры снизится колоссально. Рекомендуем использовать Табель только для регистрации тех случаев, которые невозможно зафиксировать иными документами. Переход на расчет по графикам — это самый эффективный способ «ускорения», так как документ просто перестает существовать.
Если методологический отказ от табеля невозможен, проанализируем ситуацию на уровне СУБД. Время в 30 секунд на запись часто свидетельствует о том, что SQL-сервер выбирает неверный план выполнения запроса. Выполним следующие действия:
Index Scan вместо Index Seek. Выполним регламентную операцию UPDATE STATISTICS для таблиц регистров расчета.Записать().Рассмотрим, что мы можем изменить непосредственно в конфигурации для ускорения процесса:
1. Использование привилегированного режима. Если задержка вызвана RLS, мы можем обернуть запись набора записей в привилегированный модуль. Рассмотрим пример:
УстановитьПривилегированныйРежим(Истина);
НаборЗаписей.Записать();
УстановитьПривилегированныйРежим(Ложь);
Это позволит системе игнорировать проверку прав доступа в момент записи в таблицы БД, что может ускорить процесс в несколько раз.
2. Дробление документов. Если в одном табеле 1000 сотрудников, время его проведения будет расти нелинейно. Порекомендуем пользователям разбивать табели по подразделениям. Документ на 50-100 строк проводится мгновенно, а суммарное время проведения десяти маленьких документов часто меньше, чем одного огромного, из-за особенностей работы с памятью и блокировками.
3. Отключение автоматических пересчетов. При записи табеля система часто пытается зарегистрировать необходимость пересчета зарплаты в регистре сведений ПересчетыЗарплаты. Проанализируем, насколько критично выполнять это немедленно. В ряде случаев регистрацию пересчетов можно вынести в фоновое задание, чтобы основной поток пользователя не простаивал.
Для ускорения проведения табеля мы рекомендуем действовать комплексно:
НаборЗаписей.Записать()).Следуя этим шагам, можно добиться сокращения времени проведения документа с 50 секунд до приемлемых 2–5 секунд даже на больших объемах данных.