В чем разница в производительности между условиями «В ИЕРАРХИИ» и «Родитель = &Группа» в запросах 1С?

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

При разработке запросов к иерархическим справочникам часто возникает дилемма: использовать строгое равенство по реквизиту Родитель или универсальное условие В ИЕРАРХИИ. На небольших базах разница во времени выполнения незаметна, однако на объемах в сотни тысяч и миллионы записей выбор конструкции напрямую влияет на стабильность всей системы. Разберем по шагам, как работают эти конструкции на уровне СУБД, какие риски несет рекурсивный поиск и как правильно оптимизировать иерархические выборки.

Как платформа и СУБД обрабатывают условия фильтрации

Чтобы понять разницу в быстродействии, проанализируем поведение оптимизатора СУБД при выполнении каждого из вариантов.

  1. Прямое сравнение (Родитель = &Группа): Платформа 1С транслирует такое условие в простой предикат SQL вида WHERE _ParentIDRRef = @P. Поле родителя входит в состав стандартных индексов таблицы справочника. СУБД выполняет точечный поиск по индексу (Index Seek), что занимает доли миллисекунды независимо от общего размера таблицы (будь то 10 тысяч или 5 миллионов строк).
  2. Условие «В ИЕРАРХИИ»: Для вычисления всех потомков выбранной группы платформа генерирует рекурсивный запрос (с использованием CTE — Common Table Expression) либо предварительно формирует список всех узлов-родителей, после чего выполняет условие В СПИСКЕ. Чем больше глубина вложенности и количество подчиненных групп, тем больше ресурсов требуется для обхода дерева. В таких СУБД, как PostgreSQL, рекурсивные CTE часто материализуются в памяти или во временных таблицах на диске, вызывая дополнительную дисковую нагрузку.

Критические риски использования «В ИЕРАРХИИ»

Выясним причину, почему универсальное условие В ИЕРАРХИИ может стать узким местом производительности:

  1. Использование в параметрах виртуальных таблиц: Передача условия Номенклатура В ИЕРАРХИИ (&Группа) в параметры виртуальной таблицы регистра (например, остатков или оборотов) является грубой ошибкой проектирования. Оптимизатор СУБД не может эффективно связать составной индекс итогов регистра с динамически вычисляемым деревом и переходит к полному сканированию всей таблицы итогов (Index Scan / Clustered Index Scan).
  2. Передача пустой ссылки: Если в параметр передать пустую ссылку или неинициализированное значение, платформа может инициировать сканирование всей иерархии справочника, что приведет к длительной блокировке и зависанию сеанса.
  3. Работа механизма RLS: Использование иерархических условий в ограничениях доступа на уровне записей перемножает нагрузку на каждый пользовательский запрос к данным.

Способы оптимизации и альтернативные решения

Рассмотрим практические методы, позволяющие сохранить гибкость иерархии и при этом обеспечить максимальную скорость выполнения запросов.

Вариант 1. Пакетный запрос с индексированной временной таблицей

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

Посмотрим на пример правильного построения пакетного запроса:


ВЫБРАТЬ
    Номенклатура.Ссылка КАК Номенклатура
ПОМЕСТИТЬ ВТ_ЭлементыИерархии
ИЗ
    Справочник.Номенклатура КАК Номенклатура
ГДЕ
    Номенклатура.Ссылка В ИЕРАРХИИ(&ГруппаНоменклатуры)
    И НЕ Номенклатура.ЭтоГруппа

ИНДЕКСИРОВАТЬ ПО
    Номенклатура
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
    Остатки.Номенклатура КАК Номенклатура,
    Остатки.КоличествоОстаток КАК Количество
ИЗ
    РегистрНакопления.ТоварыНаСкладах.Остатки(
            &Период,
            Номенклатура В
                (ВЫБРАТЬ
                    ВТ_ЭлементыИерархии.Номенклатура
                ИЗ
                    ВТ_ЭлементыИерархии)) КАК Остатки

Такой подход гарантирует, что в виртуальную таблицу регистра будет передан фиксированный список ссылок, и СУБД задействует штатный индекс таблицы итогов.

Вариант 2. Денормализация структуры (хранение корня иерархии)

Если иерархия справочника стабильна, а выборки по крупным веткам каталога выполняются часто и критичны к скорости, применим денормализацию:

  1. Добавим в справочник реквизит ГруппаВерхнегоУровня (или КореньИерархии) с признаком Индексировать.
  2. В модуле объекта при записи автоматически определим и заполним этот реквизит ссылкой на родительскую группу 1-го уровня.
  3. В запросах заменим рекурсивный отбор на прямое сравнение:

ВЫБРАТЬ
    Номенклатура.Ссылка КАК Ссылка,
    Номенклатура.Артикул КАК Артикул
ИЗ
    Справочник.Номенклатура КАК Номенклатура
ГДЕ
    Номенклатура.ГруппаВерхнегоУровня = &НужнаяГруппа
    И НЕ Номенклатура.ЭтоГруппа

Этот метод полностью устраняет накладные расходы на обход дерева, сохраняя быстродействие на уровне прямого равенства даже при миллионных объемах данных.

Вариант 3. Использование строгого равенства при регламентированной структуре

Если бизнес-процесс компании строго определяет, что элементы справочника располагаются исключительно на первом уровне вложенности выбранной папки и создание подпапок запрещено правами доступа, смело используем прямое условие Родитель = &НужнаяГруппа. Это избавит СУБД от построения планов с рекурсией и обеспечит минимальное время отклика.

← На главную