Сравнение способов выбора данных из табличных частей в 1С: какой запрос предпочтительнее?

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

При разработке запросов в системе «1С:Предприятие 8» программисты часто сталкиваются с необходимостью объединения данных из «шапки» документа и его табличной части. На первый взгляд, существует несколько синтаксически верных способов решить эту задачу, которые кажутся идентичными. Однако при детальном анализе выясняется, что они по-разному нагружают сервер СУБД и возвращают разные наборы данных. В этой статье мы подробно разберем три основных варианта написания таких запросов, проанализируем их производительность и выясним, какой из них лучше использовать в различных ситуациях.

Вариант 1: Обращение к реквизитам шапки через «точку»

Рассмотрим первый вариант, который часто используется из-за своей лаконичности. В этом случае основной таблицей запроса выступает табличная часть документа, а данные шапки выбираются через обращение к полю Ссылка.


ВЫБРАТЬ
    ЗаказТовары.Номенклатура КАК Номенклатура,
    ЗаказТовары.Сумма КАК Сумма,
    ЗаказТовары.Ссылка.Организация КАК Организация,
    ЗаказТовары.Ссылка.Контрагент КАК Контрагент
ИЗ
    Документ.Заказ.Товары КАК ЗаказТовары

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

Производительность: С точки зрения SQL, современные версии платформы «1С» (начиная с 8.2) оптимизируют такие обращения. Несмотря на то, что в коде мы дважды обращаемся через «точку» (к организации и контрагенту), платформа создаст в SQL-запросе только одно левое соединение с основной таблицей документа. Это делает данный вариант достаточно производительным и легким для чтения.

Вариант 2: Явное левое соединение

Второй вариант предполагает использование классического SQL-подхода с явным соединением двух таблиц. Здесь основной таблицей выступает «шапка» документа.


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

Анализ логики: Проанализируем ситуацию с пустыми табличными частями. В отличие от первого варианта, ЛЕВОЕ СОЕДИНЕНИЕ гарантирует, что в результат попадут все документы Заказ, подходящие под условия фильтрации. Если у заказа нет товаров, в полях Номенклатура и Сумма мы получим значение NULL, но сама запись о документе (организация и контрагент) сохранится.

Производительность: Этот метод считается стандартом де-факто для сложных отчетов. Он дает разработчику полный контроль над типом соединения (Левое, Внутреннее, Полное). Однако стоит учитывать, что если нам нужны данные только по заполненным ТЧ, этот вариант может работать чуть медленнее первого из-за большего количества сканируемых записей в основной таблице (как показано в обсуждении на форуме, разница в количестве RecordsScanned может быть существенной).

Вариант 3: Использование вложенных таблиц

Третий вариант является специфичным для платформы «1С». Он часто генерируется конструктором печати и позволяет получить иерархическую структуру прямо в результате запроса.


ВЫБРАТЬ
    Заказ.Организация КАК Организация,
    Заказ.Контрагент КАК Контрагент,
    Заказ.Товары.(
        Номенклатура КАК Номенклатура,
        Сумма КАК Сумма
    ) КАК ЗаказТовары
ИЗ
    Документ.Заказ КАК Заказ

Анализ логики: Выясним, почему этот вариант так популярен в печатных формах. При обходе результата такого запроса методом Выбрать(), мы получаем объект ВыборкаИзРезультатаЗапроса, внутри которого поле ЗаказТовары само является выборкой. Это позволяет писать изящный код обхода «цикл в цикле» без ручной проверки смены ссылки документа.

Скрытые механизмы и риски: Рассмотрим, что происходит «под капотом». Платформа транслирует этот запрос в SQL через создание временных таблиц (как видно из трассировки профайлера в сообщении №2). Сначала данные шапок помещаются во временную таблицу #tt2, а затем к ней присоединяются данные ТЧ.

  1. Создание временных таблиц дает дополнительную нагрузку на базу данных tempdb.
  2. Если объем данных велик, время на формирование и передачу вложенных структур может превысить время выполнения «плоского» запроса.
  3. Такой синтаксис нельзя использовать в качестве источника данных для других соединений или внутри объединений (ОБЪЕДИНИТЬ ВСЕ).

Влияние системы прав доступа (RLS)

Проанализируем критически важный аспект, который не всегда очевиден при разработке под полными правами. Если в конфигурации настроены ограничения доступа на уровне записей (RLS):

Итоги и рекомендации

Выясним, какой же вариант в итоге предпочтительнее. Ответ зависит от конкретной задачи:

  1. Для отчетов на СКД (Система компоновки данных): Рекомендуем использовать Вариант 1 или Вариант 2. СКД — это мощный движок, который сам умеет группировать данные и оптимизировать соединения. Использование вложенных таблиц (Вариант 3) в СКД практически бессмысленно и может вызвать ошибки.
  2. Для простых печатных форм: Вариант 3 допустим и удобен. Он сокращает объем кода на встроенном языке за счет удобного обхода вложенных выборок. Однако при работе с документами, содержащими тысячи строк ТЧ, лучше перейти к плоской таблице (Вариант 1 или 2).
  3. Для высоконагруженных систем и больших выборок: Однозначно выбираем Вариант 1 (если не нужны пустые ТЧ) или Вариант 2 (если нужны все документы). Они наиболее прозрачно транслируются в SQL и позволяют оптимизатору СУБД построить эффективный план выполнения.
  4. Контроль пустых значений: Если вашей бизнес-логике важно видеть заказы без строк (например, для анализа забытых черновиков), используйте только Вариант 2 с ЛЕВЫМ СОЕДИНЕНИЕМ.

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

← На главную