Проблема быстродействия списка сотрудников в конфигурации 1С:Зарплата и Управление Персоналом 3.1 (особенно в версии КОРП) часто становится критической при достижении штатной численности в несколько десятков тысяч человек. Начиная с релизов ветки 3.1.9, идеология работы со списком изменилась: вместо прямой работы со справочником используется специализированный механизм на базе динамического списка. В этой статье мы подробно разберем, почему список может тормозить, как проанализировать типовой запрос и какие шаги предпринять для оптимизации системы на СУБД PostgreSQL или MS SQL Server.
Для начала выясним причину, по которой типовое решение работает именно так. В старых версиях 1С:ЗУП для вывода текущего подразделения, должности или состояния сотрудника (в отпуске, на больничном) системе приходилось «на лету» выполнять тяжелые расчеты, обращаясь к кадровым регистрам и регистрам расчета. На больших базах это приводило к невозможности комфортной работы.
Для решения этой проблемы был введен регистр сведений ДанныеДляПодбораСотрудников. Это денормализованная таблица, в которую регламентными заданиями Обновление данных для подбора сотрудников и Заполнение данных для подбора сотрудников «схлопываются» все актуальные сведения. Динамический список формы сотрудников теперь строится именно на этом регистре. Однако при объемах данных свыше 50 000 – 70 000 записей даже эта оптимизация может давать сбои, особенно под нагрузкой RLS (разграничения прав доступа).
Рассмотрим структуру запроса, который система выполняет при открытии формы списка. Основная часть данных извлекается из регистра ДанныеДляПодбораСотрудников, который соединяется со справочником Сотрудники и множеством других регистров сведений для получения дополнительных колонок (ФОТ, надбавки, роли и т.д.).
Типовой фрагмент запроса выглядит следующим образом:
ИЗ РегистрСведений.ДанныеДляПодбораСотрудников КАК ДанныеДляПодбора
ВНУТРЕННЕЕ СОЕДИНЕНИЕ Справочник.Сотрудники КАК Сотрудники
ПО ДанныеДляПодбора.Сотрудник = Сотрудники.Ссылка
И ДанныеДляПодбора.Наименование = Сотрудники.Наименование
И (ДанныеДляПодбора.ИдентификаторЗаписи В (
ВЫБРАТЬ ПЕРВЫЕ 1 ДанныеДляПодбораСотрудниковОтбор.ИдентификаторЗаписи
ИЗ РегистрСведений.ДанныеДляПодбораСотрудников КАК ДанныеДляПодбораСотрудниковОтбор
ГДЕ ДанныеДляПодбораСотрудниковОтбор.Сотрудник = ДанныеДляПодбора.Сотрудник
УПОРЯДОЧИТЬ ПО ДанныеДляПодбораСотрудниковОтбор.Начало УБЫВ))
Проанализируем ситуацию: использование конструкции ВЫБРАТЬ ПЕРВЫЕ 1 внутри условия соединения В для каждой строки основного запроса крайне неэффективно для PostgreSQL. Планировщик запросов может ошибочно выбрать метод вложенных циклов (Nested Loops), что на 70 000 записей приведет к ожиданию открытия формы в течение нескольких минут.
Если ваша база данных работает медленно, одним из эффективных способов будет вынос формы списка в расширение и модификация текста запроса динамического списка. Разберем, что именно можно оптимизировать:
ФизическомуЛицу и Сотруднику одновременно. Поскольку Сотрудник уже является уникальным ключом, дополнительные поля в ПО только усложняют работу оптимизатора СУБД.РолиСотрудников (для работников и договорников). Проанализируем, как это можно упростить:
// Вместо двух соединений:
{ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.РолиСотрудников КАК РолиСотрудников
ПО ДанныеДляПодбора.Сотрудник = РолиСотрудников.Сотрудник}
// В поле ВЫБРАТЬ используем условие:
ВЫБОР КОГДА РолиСотрудников.РольСотрудника = ЗНАЧЕНИЕ(Перечисление.РолиСотрудников.Работник)
ТОГДА ИСТИНА ИНАЧЕ ЛОЖЬ КОНЕЦ КАК ЭтоРаботник
Такой подход сокращает количество соединений (JOIN), что критически важно для производительности динамического списка.
В ЗУП КОРП основной причиной тормозов почти всегда является механизм разграничения прав доступа. Если в базе настроен доступ по организациям или подразделениям, 1С добавляет к каждому запросу огромный блок условий. Проанализируем состояние системы: если под пользователем с полными правами список «летает», а под обычным кадровиком — «висит», проблема в RLS.
Что нужно сделать:
Производительный RLS (доступен в последних версиях платформы 8.3). Он использует заранее рассчитанные таблицы прав вместо динамического вычисления условий.Обновление прав доступа.Для систем на PostgreSQL критически важно состояние статистики. Если статистика по регистру ДанныеДляПодбораСотрудников устарела, Postgres может построить неверный план выполнения, игнорируя существующие индексы.
Рекомендуем выполнить следующие действия:
ANALYZE для таблиц этого регистра.Наименование (для быстрого поиска по ФИО). Однако, если вы чаще фильтруете список по Организации или Подразделению, СУБД может выполнять сканирование всей таблицы.Иногда проблема кроется в привычках пользователей. Поиск «по всей строке» (когда в строку поиска просто пишется «Иванов») заставляет систему искать вхождение подстроки во всех индексированных полях. На 70 000 сотрудников это гарантированный Full Table Scan.
Разберем рекомендации для пользователей:
ФОТ или Тарифная ставка), через меню Еще — Настроить список. Каждая скрытая колонка убирает соответствующий LEFT JOIN из SQL-запроса.Оптимизация списка сотрудников в ЗУП 3.1 — это комплексная задача. Мы выяснили, что в первую очередь необходимо проверить работу регламентных заданий по обновлению данных для подбора, затем проанализировать влияние RLS и, при необходимости, упростить текст запроса в расширении, удалив избыточные соединения. Правильная настройка индексов СУБД и обучение пользователей методам быстрого поиска позволят добиться комфортной работы даже на базах с численностью персонала более 70 000 человек.