При работе с крупными базами 1С:Зарплата и Управление Персоналом, особенно в редакциях 2.0 и 2.5, разработчики часто сталкиваются с проблемой производительности «тяжелых» отчетов. Ситуация, когда отчет по штатному расписанию, содержащий десятки временных таблиц и срезов последних, нужно сформировать не на одну дату, а в динамике за год, может привести к значительному ожиданию. Рассмотрим, как превратить отчет, формирующийся 5 минут, в быстрый и эффективный инструмент.
В нашем сценарии запрос содержит 2050 строк кода, 20 временных таблиц и 9 виртуальных таблиц СрезПоследних. Когда мы запускаем такой запрос в цикле 12 раз (по количеству месяцев), система выполняет колоссальный объем лишней работы. Разберем по шагам, что происходит на уровне СУБД: при каждой итерации цикла заново создаются временные таблицы в базе tempdb, заново рассчитываются срезы последних и заново строятся индексы. Если суммарное время выполнения составляет 5 минут, это означает, что каждая итерация занимает около 25–30 секунд. Для 13 тысяч сотрудников это приемлемый результат для разового отчета, но при частом использовании или росте штата это станет «бутылочным горлышком».
Самый эффективный способ оптимизации — это отказ от выполнения запроса в цикле Для ... По ... Цикл. Вместо этого мы можем модифицировать запрос так, чтобы он получал данные сразу на 12 дат (концы месяцев) за один проход. Выясним, как это реализовать технически.
Рассмотрим алгоритм создания среза последних на несколько дат:
ВТ_Даты, в которую поместим 12 строк с интересующими нас датами среза.СрезПоследних, обратимся к физической таблице регистра сведений.ВТ_Даты по условию Регистр.Период <= ВТ_Даты.Дата.ВТ_Даты.Дата и ключевым полям регистра (например, Сотрудник или Должность), вычислив МАКСИМУМ(Регистр.Период).Этот метод позволяет СУБД оптимизировать план запроса сразу для всего периода, что зачастую в 3–5 раз быстрее, чем 12 отдельных обращений.
Проанализируем структуру запроса. Наличие 20 временных таблиц (ВТ) требует особого внимания к индексам. В 1С временные таблицы не индексируются автоматически. Если ВТ_Штатка соединяется с ВТ_Сотрудники по полю Сотрудник, и в обеих таблицах тысячи строк, СУБД будет вынуждена использовать вложенные циклы, что крайне медленно.
Посмотрим на пример правильной индексации в тексте запроса:
// Фрагмент оптимизированного запроса
ВЫБРАТЬ
ШтатноеРасписание.Сотрудник КАК Сотрудник,
ШтатноеРасписание.Подразделение КАК Подразделение
ПОМЕСТИТЬ ВТ_ОсновныеДанные
ИЗ
РегистрСведений.ШтатнаяРасстановка КАК ШтатноеРасписание
ИНДЕКСИРОВАТЬ ПО
Сотрудник,
Подразделение
;
Важно помнить: индексировать нужно только те поля, которые участвуют в секциях ПО (условия соединения) или ГДЕ последующих запросов пакета. Избыточная индексация также может замедлить работу из-за затрат на построение индексов.
Если запрос настолько сложен, что его переработка займет недели, применим метод «разделяй и властвуй». Мы можем запустить расчет каждого квартала (по 3 месяца) в отдельном фоновом задании. Современные серверы имеют многоядерные процессоры, и распараллеливание позволит выполнить 4 части отчета одновременно.
Разберем по шагам реализацию:
ФоновыеЗадания.Выполнить() для запуска нескольких потоков.ФоновыеЗадания.ОжидатьЗавершения().Этот подход может сократить время формирования с 5 минут до 1–1.5 минут без глубокого переписывания логики самого запроса.
Прежде чем приступать к оптимизации, необходимо точно выяснить, где теряется время. Выясним причину задержки, используя встроенный Замер производительности. Часто оказывается, что сам запрос выполняется быстро, а основное время тратится на вывод данных в ПолеТабличногоДокумента или на расчет итогов в СистемеКомпоновкиДанных (СКД).
Если проблема в выводе, проанализируем настройки СКД: возможно, стоит отключить избыточные группировки или перенести часть вычислений из Вычисляемых полей непосредственно в текст запроса. 1С эффективнее обрабатывает данные на стороне СУБД, чем на языке выражений компоновки.
Если отчет «Штатная расстановка за год» требуется руководителям по утрам, хорошим решением будет использование механизма регламентных заданий. Мы можем настроить автоматическое формирование данных ночью и сохранение их в специальный регистр сведений (кэш) или во временное хранилище. В таком случае пользователь при открытии отчета мгновенно получит уже готовые цифры.
Подведем итог: для оптимизации тяжелых отчетов в ЗУП 2.0/2.5 наиболее предпочтительным является переход от циклов к пакетным запросам с использованием временных таблиц дат и обязательной индексацией ключевых полей. Если же время поджимает, распараллеливание через ФоновыеЗадания станет отличным временным решением, позволяющим сохранить нервы пользователям и расчетчикам.