Влияние ограничения иерархии на производительность запросов в 1С:Предприятие 8

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

Вопрос о производительности иерархических справочников часто встречается на собеседованиях для разработчиков 1С уровня Middle и Senior. На первый взгляд он кажется абстрактным, но за ним стоит глубокое понимание того, как метаданные 1С транслируются в физические таблицы СУБД и как платформа оптимизирует работу с древовидными структурами. Рассмотрим подробно ситуацию, когда у нас есть два идентичных по количеству элементов справочника (один с ограничением в 7 уровней, другой — без), и выясним, какой из них будет работать быстрее при обращении к элементу на 3-м уровне вложенности.

Физическая структура таблиц в СУБД

Для начала проанализируем, как иерархия хранится в базе данных. Независимо от того, стоит ли в конфигураторе флаг «Ограничение уровней» или нет, платформа 1С использует классическую модель Adjacency List (список смежности). Рассмотрим структуру таблицы на уровне SQL:

В обоих случаях в таблице справочника будет присутствовать поле _ParentIDRRef (ссылка на родителя). Никаких дополнительных полей «Уровень» или «Путь до корня» в физической таблице по умолчанию не создается. Индексация также идентична: платформа автоматически создает индекс по полям Parent + Ref, что позволяет быстро находить подчиненные элементы для конкретного узла.

Следовательно, если мы выполняем прямой запрос к элементу по его ссылке, например:


ВЫБРАТЬ
    Спр.Наименование
ИЗ
    Справочник.Тестовый КАК Спр
ГДЕ
    Спр.Ссылка = &Ссылка

Разницы в производительности не будет абсолютно никакой. СУБД выполнит поиск по первичному ключу (Clustered Index Seek), и наличие настроек иерархии в метаданных никак не повлияет на план запроса.

Работа оператора В ИЕРАРХИИ

Ситуация кардинально меняется, когда мы начинаем работать с иерархическими связями. Разберем по шагам, как платформа 1С обрабатывает условие В ИЕРАРХИИ. Проанализируем ситуацию: нам нужно найти все дочерние элементы для узла 3-го уровня.

Для справочника с ограниченной иерархией (например, 7 уровней) платформа заранее «знает» максимально возможную глубину дерева. Это теоретически позволяет ей сформировать один SQL-запрос с фиксированным количеством соединений таблицы самой с собой (LEFT JOIN). Например, для 3-х уровней это могло бы выглядеть как цепочка соединений по полю _ParentID.

Для справочника с неограниченной иерархией платформа не может предсказать глубину. В старых версиях платформы или при определенных условиях 1С использует итерационный подход:

  1. Выбираются непосредственные потомки узла.
  2. Если потомки найдены, выполняется следующий запрос для поиска их потомков.
  3. Процесс повторяется до тех пор, пока выборка не станет пустой.

Однако в современных версиях платформы и для современных СУБД (MS SQL, PostgreSQL) 1С старается использовать рекурсивные запросы (CTE — Common Table Expressions). Но даже здесь наличие жесткого ограничения в 7 уровней в метаданных может подсказать оптимизатору платформы более эффективный способ построения текста запроса.

Вычисление виртуального поля Уровень

В языке запросов 1С существует возможность получить уровень элемента. Важно понимать, что это поле виртуальное. Рассмотрим, что происходит при обращении к нему:


ВЫБРАТЬ
    Спр.Ссылка,
    Спр.Уровень() КАК УровеньЭлемента
ИЗ
    Справочник.Тестовый КАК Спр

Поскольку в таблице SQL нет колонки Level, платформе приходится вычислять её «на лету». Это делается путем обхода дерева вверх до родителя, у которого поле _ParentID равно NULL (пустая ссылка). Если иерархия ограничена 7 уровнями, алгоритм поиска корня имеет жесткий предел. Для неограниченного справочника теоретически проверка может длиться дольше, если данные в базе некорректны (например, возникло зацикливание, хотя платформа 1С старается этого не допускать при записи).

Особенности файлового варианта и программные проверки

Проанализируем результаты замеров из практики (сообщение 3 в обсуждении), где неограниченный справочник показал большую скорость. На первый взгляд это парадокс, но он имеет техническое объяснение. Выясним причину:

При записи и чтении объектов с ограниченной иерархией движок 1С выполняет дополнительные программные проверки. Платформа должна контролировать, чтобы при интерактивном переносе элемента или программной записи не был превышен лимит в 7 уровней. Эти проверки встроены в объектную модель СправочникОбъект и в механизмы работы файловой СУБД.

В случае с неограниченной иерархией часть этих проверок в программном коде платформы просто отсутствует (пропускается). В масштабе миллионов операций или при специфических замерах в Технологическом журнале это может дать микросекундное преимущество справочнику без ограничений, так как «лишний» код по контролю лимита не исполняется.

Резюме и ответ на вопрос

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

1. Если это простой запрос (выборка по ссылке): Разницы в производительности нет, так как структура индексов и таблиц в SQL идентична.

2. Если используется оператор В ИЕРАРХИИ: Справочник с ограничением (7 уровней) может быть быстрее в серверном варианте, так как платформа может построить более предсказуемый и оптимизированный план SQL-запроса с ограниченным числом соединений.

3. Если оценивается общая работа системы (включая запись): Справочник с неограниченной иерархией может работать чуть быстрее из-за отсутствия накладных расходов на программный контроль лимита уровней со стороны платформы 1С.

4. Влияние уровня расположения: Тот факт, что элемент находится именно на 3-м уровне, в данном случае нивелирует разницу между 7 и "бесконечностью", так как в обоих случаях глубина поиска (3 шага) одинакова. Основное влияние оказывают именно настройки метаданных, заставляющие платформу выбирать тот или иной алгоритм трансляции запроса в SQL.

← На главную