В конфигурации 1С:Зарплата и Управление Персоналом 2.5 (ЗУП 2.5) отчеты по персональным данным часто становятся «узким местом» производительности. Когда необходимо собрать воедино данные справочника ФизическиеЛица, паспортные данные из регистров сведений и контактную информацию, запрос может выполняться недопустимо долго. Рассмотрим причины низкой скорости и разберем по шагам, как превратить тяжеловесный запрос в эффективный инструмент.
Проанализируем первую часть исходного запроса. Зачастую разработчики выбирают всех физических лиц из справочника, включая тех, кто давно уволен или вообще никогда не принимался на работу. Если в базе десятки тысяч записей, это создает колоссальную нагрузку. Первое правило оптимизации — максимально сузить выборку еще на этапе формирования первой временной таблицы.
Вместо того чтобы просто фильтровать по родителю или пометке удаления, рассмотрим ситуацию, когда нам нужны только актуальные сотрудники. В этом случае эффективнее начинать выборку с регистра сведений РаботникиОрганизаций или справочника Сотрудники, чтобы получить список только тех физлиц, которые действительно важны для отчета.
В исходном коде создается временная таблица ВТ_ОбщееФизЛица. Однако при последующих соединениях система вынуждена каждый раз полностью сканировать эту таблицу (Table Scan), так как в ней отсутствуют индексы. Выясним, как это исправить.
Для ускорения работы левых соединений (LEFT JOIN) необходимо индексировать поля связи. Разберем на примере:
ВЫБРАТЬ
ФизическиеЛица.Ссылка КАК ФизЛицо,
ФизическиеЛица.ДатаРождения,
ФизическиеЛица.ИНН
ПОМЕСТИТЬ ВТ_ОбщееФизЛица
ИЗ
Справочник.ФизическиеЛица КАК ФизическиеЛица
ГДЕ
ФизическиеЛица.ПометкаУдаления = ЛОЖЬ
И ФизическиеЛица.ЭтоГруппа = ЛОЖЬ
;
ИНДЕКСИРОВАТЬ ПО
ФизЛицо
;
Добавление инструкции ИНДЕКСИРОВАТЬ ПО позволит СУБД мгновенно находить нужные строки при соединении с другими таблицами в последующих пакетах.
Проанализируем ситуацию с контактной информацией (КИ). В исходном запросе используется ОБЪЕДИНИТЬ ВСЕ и тяжелая агрегатная функция МАКСИМУМ с использованием ПОДСТРОКА. Это одна из самых ресурсоемких операций. Регистр сведений КонтактнаяИнформация в ЗУП 2.5 имеет специфическую структуру, и соединение с ним «в лоб» через объединения заставляет систему выполнять несколько проходов по одной и той же таблице.
Рассмотрим более изящный способ: использование нескольких левых соединений к одной таблице регистра по разным видам контактной информации. Это позволит избежать лишних группировок. Посмотрим на пример кода:
ВЫБРАТЬ
ВТ.ФизЛицо,
КИ_Адрес.Представление КАК АдресПроживания,
КИ_Телефон.Представление КАК ТелефонМобильный
ИЗ
ВТ_ОбщееФизЛица КАК ВТ
ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.КонтактнаяИнформация КАК КИ_Адрес
ПО ВТ.ФизЛицо = КИ_Адрес.Объект
И КИ_Адрес.Тип = ЗНАЧЕНИЕ(Перечисление.ТипыКонтактнойИнформации.Адрес)
И КИ_Адрес.Вид = ЗНАЧЕНИЕ(Справочник.ВидыКонтактнойИнформации.ФактАдресФизЛица)
ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.КонтактнаяИнформация КАК КИ_Телефон
ПО ВТ.ФизЛицо = КИ_Телефон.Объект
И КИ_Телефон.Тип = ЗНАЧЕНИЕ(Перечисление.ТипыКонтактнойИнформации.Телефон)
И КИ_Телефон.Вид = ЗНАЧЕНИЕ(Справочник.ВидыКонтактнойИнформации.ТелефонФизЛица)
В этом случае мы получаем данные за один проход, а индексы регистра по полям Объект, Тип и Вид обеспечивают максимальное быстродействие.
В последнем пакете исходного запроса была допущена критическая ошибка: таблицы перечислены через запятую без условий связи (ПО ...). В терминах SQL это называется Cross Join. Если в первой таблице 100 записей, а во второй 100, результат будет содержать 10 000 строк. На реальных базах это приводит к зависанию системы и переполнению памяти.
Рассмотрим правильный подход к сборке финальной таблицы. Все данные должны быть строго связаны по полю ФизЛицо. При этом важно использовать ЛЕВОЕ СОЕДИНЕНИЕ, чтобы не потерять людей, у которых, например, не заполнен телефон или паспортные данные.
Разберем по шагам, как должен выглядеть качественный запрос для ЗУП 2.5:
СрезПоследних. Важно передавать список физлиц в параметры виртуальной таблицы через условие ФизЛицо В (ВЫБРАТЬ ФизЛицо ИЗ ВТ_ОбщееФизЛица). Это позволит платформе оптимизировать SQL-запрос на уровне СУБД.ЛЕВОЕ СОЕДИНЕНИЕ и указывая четкие условия связи по ФизЛицо.Проанализируем также использование функции ПОДСТРОКА. В ЗУП 2.5 поле Представление в контактной информации может иметь неограниченную длину. Если вам необходимо использовать это поле в группировке (СГРУППИРОВАТЬ ПО), то ПОДСТРОКА обязательна. Но если вы используете предложенную выше схему с левыми соединениями без группировок, от этой функции можно отказаться, что также немного ускорит работу.
Соблюдение этих правил позволит сократить время выполнения отчета с нескольких минут до нескольких секунд даже на базах с большим объемом данных.