Как ускорить работу списка сотрудников в 1С:ЗУП 3.1 на больших базах?

Программист 1С v8.3 (Управляемые формы) 1С:Зарплата и Управление Персоналом
← На главную

Проблема быстродействия списка сотрудников в конфигурации 1С:Зарплата и Управление Персоналом 3.1 (особенно в версии КОРП) часто становится критической при достижении штатной численности в несколько десятков тысяч человек. Начиная с релизов ветки 3.1.9, идеология работы со списком изменилась: вместо прямой работы со справочником используется специализированный механизм на базе динамического списка. В этой статье мы подробно разберем, почему список может тормозить, как проанализировать типовой запрос и какие шаги предпринять для оптимизации системы на СУБД PostgreSQL или MS SQL Server.

Причины изменения архитектуры списка

Для начала выясним причину, по которой типовое решение работает именно так. В старых версиях 1С:ЗУП для вывода текущего подразделения, должности или состояния сотрудника (в отпуске, на больничном) системе приходилось «на лету» выполнять тяжелые расчеты, обращаясь к кадровым регистрам и регистрам расчета. На больших базах это приводило к невозможности комфортной работы.

Для решения этой проблемы был введен регистр сведений ДанныеДляПодбораСотрудников. Это денормализованная таблица, в которую регламентными заданиями Обновление данных для подбора сотрудников и Заполнение данных для подбора сотрудников «схлопываются» все актуальные сведения. Динамический список формы сотрудников теперь строится именно на этом регистре. Однако при объемах данных свыше 50 000 – 70 000 записей даже эта оптимизация может давать сбои, особенно под нагрузкой RLS (разграничения прав доступа).

Анализ типового запроса динамического списка

Рассмотрим структуру запроса, который система выполняет при открытии формы списка. Основная часть данных извлекается из регистра ДанныеДляПодбораСотрудников, который соединяется со справочником Сотрудники и множеством других регистров сведений для получения дополнительных колонок (ФОТ, надбавки, роли и т.д.).

Типовой фрагмент запроса выглядит следующим образом:


ИЗ РегистрСведений.ДанныеДляПодбораСотрудников КАК ДанныеДляПодбора
ВНУТРЕННЕЕ СОЕДИНЕНИЕ Справочник.Сотрудники КАК Сотрудники
ПО ДанныеДляПодбора.Сотрудник = Сотрудники.Ссылка
    И ДанныеДляПодбора.Наименование = Сотрудники.Наименование
    И (ДанныеДляПодбора.ИдентификаторЗаписи В (
        ВЫБРАТЬ ПЕРВЫЕ 1 ДанныеДляПодбораСотрудниковОтбор.ИдентификаторЗаписи
        ИЗ РегистрСведений.ДанныеДляПодбораСотрудников КАК ДанныеДляПодбораСотрудниковОтбор
        ГДЕ ДанныеДляПодбораСотрудниковОтбор.Сотрудник = ДанныеДляПодбора.Сотрудник
        УПОРЯДОЧИТЬ ПО ДанныеДляПодбораСотрудниковОтбор.Начало УБЫВ))

Проанализируем ситуацию: использование конструкции ВЫБРАТЬ ПЕРВЫЕ 1 внутри условия соединения В для каждой строки основного запроса крайне неэффективно для PostgreSQL. Планировщик запросов может ошибочно выбрать метод вложенных циклов (Nested Loops), что на 70 000 записей приведет к ожиданию открытия формы в течение нескольких минут.

Шаг 1. Оптимизация соединений в расширении

Если ваша база данных работает медленно, одним из эффективных способов будет вынос формы списка в расширение и модификация текста запроса динамического списка. Разберем, что именно можно оптимизировать:

  1. Упрощение условий соединения. В типовом запросе часто встречаются избыточные связи. Например, связь по ФизическомуЛицу и Сотруднику одновременно. Поскольку Сотрудник уже является уникальным ключом, дополнительные поля в ПО только усложняют работу оптимизатора СУБД.
  2. Объединение запросов к одним и тем же таблицам. Рассмотрим пример с ролями сотрудников. В типовом коде часто встречаются два левых соединения к одному регистру РолиСотрудников (для работников и договорников). Проанализируем, как это можно упростить:

// Вместо двух соединений:
{ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.РолиСотрудников КАК РолиСотрудников
ПО ДанныеДляПодбора.Сотрудник = РолиСотрудников.Сотрудник}

// В поле ВЫБРАТЬ используем условие:
ВЫБОР КОГДА РолиСотрудников.РольСотрудника = ЗНАЧЕНИЕ(Перечисление.РолиСотрудников.Работник) 
      ТОГДА ИСТИНА ИНАЧЕ ЛОЖЬ КОНЕЦ КАК ЭтоРаботник

Такой подход сокращает количество соединений (JOIN), что критически важно для производительности динамического списка.

Шаг 2. Настройка «Производительного RLS»

В ЗУП КОРП основной причиной тормозов почти всегда является механизм разграничения прав доступа. Если в базе настроен доступ по организациям или подразделениям, 1С добавляет к каждому запросу огромный блок условий. Проанализируем состояние системы: если под пользователем с полными правами список «летает», а под обычным кадровиком — «висит», проблема в RLS.

Что нужно сделать:

  1. Убедиться, что в настройках программы включен режим Производительный RLS (доступен в последних версиях платформы 8.3). Он использует заранее рассчитанные таблицы прав вместо динамического вычисления условий.
  2. Проверить актуальность регламентного задания Обновление прав доступа.
  3. Минимизировать количество групп доступа, в которые входит один пользователь.

Шаг 3. Работа с СУБД PostgreSQL

Для систем на PostgreSQL критически важно состояние статистики. Если статистика по регистру ДанныеДляПодбораСотрудников устарела, Postgres может построить неверный план выполнения, игнорируя существующие индексы.

Рекомендуем выполнить следующие действия:

Шаг 4. Настройка интерфейса для пользователей

Иногда проблема кроется в привычках пользователей. Поиск «по всей строке» (когда в строку поиска просто пишется «Иванов») заставляет систему искать вхождение подстроки во всех индексированных полях. На 70 000 сотрудников это гарантированный Full Table Scan.

Разберем рекомендации для пользователей:

Резюме

Оптимизация списка сотрудников в ЗУП 3.1 — это комплексная задача. Мы выяснили, что в первую очередь необходимо проверить работу регламентных заданий по обновлению данных для подбора, затем проанализировать влияние RLS и, при необходимости, упростить текст запроса в расширении, удалив избыточные соединения. Правильная настройка индексов СУБД и обучение пользователей методам быстрого поиска позволят добиться комфортной работы даже на базах с численностью персонала более 70 000 человек.

← На главную