Как получить данные из цепочки вложенных документов в 1С через табличные части?

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

В практике разработки на платформе 1С:Предприятие часто возникают ситуации, когда данные необходимо извлечь не из текущего объекта, а из глубоко вложенной структуры. Представьте иерархию: Документ 1 содержит в своей табличной части ссылку на Документ 2, тот, в свою очередь, в своей табличной части хранит ссылку на Документ 3, и так далее, пока мы не доберемся до нужного нам реквизита в Документе 4. Подобные задачи требуют четкого понимания архитектуры запросов и работы СУБД, чтобы не допустить критического снижения производительности системы.

В этой статье мы подробно разберем, как правильно выстраивать связи в запросе, на что обратить внимание при работе с табличными частями и как оптимизировать выборку, чтобы план запроса оставался эффективным даже на больших объемах данных.

Анализ структуры и базовый подход к соединению таблиц

Рассмотрим ситуацию, описанную автором: нам нужно пройти путь через четыре документа. Основная сложность заключается в том, что связи идут не через реквизиты шапки, а через строки табличных частей. Это означает, что для каждого документа в цепочке нам необходимо обращаться к его подчиненной таблице (табличной части).

Проанализируем базовую логику построения такого запроса. Самый простой и очевидный путь — использование последовательных ВНУТРЕННИХ СОЕДИНЕНИЙ (INNER JOIN) или ЛЕВЫХ СОЕДИНЕНИЙ (LEFT JOIN). Разберем по шагам, как должна выглядеть эта цепочка:

  1. Выбираем данные из табличной части Документ1.Товары.
  2. Соединяем её с табличной частью Документ2.Товары по ссылке, хранящейся в Документ1.Товары.Номенклатура (или ином связующем реквизите).
  3. Повторяем операцию для последующих звеньев.

Посмотрим на пример реализации такого запроса, где мы пытаемся добраться от «Заказа поставщику» до данных в «Таможенной декларации» через промежуточное «Приобретение товаров и услуг»:


ВЫБРАТЬ
    ЗаказПоставщику.Ссылка КАК СсылкаЗаказ,
    ТаможеннаяДекларацияИмпортТовары.Ссылка.Организация КАК Организация
ИЗ
    Документ.ЗаказПоставщику КАК ЗаказПоставщику
        ЛЕВОЕ СОЕДИНЕНИЕ Документ.ПриобретениеТоваровУслуг.Товары КАК ПриобретениеТоваровУслугТовары
        ПО ПриобретениеТоваровУслугТовары.ЗаказПоставщику = ЗаказПоставщику.Ссылка
            ЛЕВОЕ СОЕДИНЕНИЕ Документ.ТаможеннаяДекларацияИмпорт.Товары КАК ТаможеннаяДекларацияИмпортТовары
            ПО ТаможеннаяДекларацияИмпортТовары.ДокументПоступления = ПриобретениеТоваровУслугТовары.Ссылка
ГДЕ
    ЗаказПоставщику.Ссылка = &Ссылка

В данном примере мы видим использование ЛЕВОЕ СОЕДИНЕНИЕ. Это важно, если мы хотим получить основной документ даже в том случае, если цепочка связей где-то прерывается. Если же нам нужны только полные цепочки, следует использовать ВНУТРЕННЕЕ СОЕДИНЕНИЕ.

Проблема производительности: почему «херовый» план запроса — это реальность?

Как справедливо отмечено в обсуждении, последовательные соединения множества табличных частей могут порождать неэффективные планы запроса в SQL. Когда СУБД видит запрос с четырьмя-пятью вложенными соединениями огромных физических таблиц табличных частей, оптимизатору становится сложно определить правильный порядок сканирования индексов.

Выясним основные причины деградации производительности в таких запросах:

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

Для решения проблемы «плохого плана» проанализируем методику использования временных таблиц. Вместо одного гигантского запроса, разделим получение данных на этапы. Это позволит нам принудительно проиндексировать промежуточные результаты и упростить работу оптимизатору SQL.

Разберем алгоритм оптимизированного запроса:

  1. Шаг 1: Извлекаем необходимые ссылки из Документ1.ТабличнаяЧасть во временную таблицу ВТ_Звено1.
  2. Шаг 2: Индексируем поле связи в ВТ_Звено1.
  3. Шаг 3: Соединяем ВТ_Звено1 с табличной частью Документ2 и выгружаем результат во ВТ_Звено2.
  4. Шаг 4: Повторяем до тех пор, пока не получим финальный реквизит.

Рассмотрим пример кода для такого подхода:


// 1. Получаем ссылки на второй документ из первого
ВЫБРАТЬ РАЗЛИЧНЫЕ
    ТЧ1.ДокументСсылка2 КАК Ссылка2
ПОМЕСТИТЬ ВТ_Связи_1_2
ИЗ
    Документ.Документ1.ТабличнаяЧасть КАК ТЧ1
ГДЕ
    ТЧ1.Ссылка = &ПараметрСсылка;
ИНДЕКСИРОВАТЬ ПО
    Ссылка2;

// 2. Переходим к третьему звену
ВЫБРАТЬ РАЗЛИЧНЫЕ
    ТЧ2.ДокументСсылка3 КАК Ссылка3
ПОМЕСТИТЬ ВТ_Связи_2_3
ИЗ
    ВТ_Связи_1_2 КАК Связи
    ВНУТРЕННЕЕ СОЕДИНЕНИЕ Документ.Документ2.ТабличнаяЧасть КАК ТЧ2
    ПО Связи.Ссылка2 = ТЧ2.Ссылка;
ИНДЕКСИРОВАТЬ ПО
    Ссылка3;

Такой подход гарантирует, что на каждом этапе СУБД работает с подготовленным и ограниченным набором данных.

Работа с составными типами данных

Проанализируем еще один важный нюанс: если реквизит в табличной части, по которому идет связь, имеет составной тип (например, ДокументСсылка.Реализация и ДокументСсылка.Поступление), производительность запроса резко упадет. Это происходит потому, что SQL-сервер будет вынужден соединяться со всеми физическими таблицами, входящими в этот тип.

Решение: Всегда используйте оператор ВЫРАЗИТЬ. Это явно указывает платформе, к какой конкретно таблице нужно обращаться.

Рассмотрим правильное применение этой функции в коде запроса:


ВЫБРАТЬ
    ВЫРАЗИТЬ(ТЧ.ДокументОснование КАК Документ.ПриобретениеТоваровУслуг).Организация КАК Организация
ИЗ
    Документ.ЗаказПоставщику.Товары КАК ТЧ

Применение ВЫРАЗИТЬ в условиях ПО при соединениях также критически важно для производительности в высоконагруженных системах.

Использование критериев отбора

Иногда вместо написания сложных запросов к вложенным табличным частям эффективнее использовать встроенный механизм платформы — Критерии отбора. Если в вашей конфигурации настроен критерий (например, СвязанныеДокументы), вы можете программно получить список всех подчиненных объектов гораздо быстрее. Однако это подходит больше для формирования отчетов или списков в интерфейсе, чем для массовой обработки данных в одном запросе.

Резюме и рекомендации

Подведем итоги. Для построения надежной архитектуры запроса при получении данных из цепочки документов придерживайтесь следующих правил:

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

← На главную