Зачем использовать несколько наборов данных в СКД вместо обычного соединения в запросе?

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

При разработке отчетов в системе компоновки данных (СКД) разработчики часто сталкиваются с дилеммой: написать один большой монолитный запрос с несколькими соединениями таблиц или разделить выборку на отдельные наборы данных и связать их на вкладке Связи наборов данных. На первый взгляд, традиционное соединение на уровне СУБД кажется более привычным, однако механизм связывания наборов данных в СКД решает целый ряд специфических архитектурных и прикладных задач. Разберем детально, когда и почему целесообразно использовать раздельные наборы данных.

Корректный расчет итоговых данных без задвоения

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

Для решения этой проблемы в СКД применяется разделение данных:

  1. В первом наборе данных (НаборДанныхДокументы) мы выбираем реквизиты шапки документа и его общую сумму.
  2. Во втором наборе данных (НаборДанныхСостав) выбираем строки табличной части с номенклатурой и количеством.
  3. Связываем эти наборы по ключевому полю Ссылка.

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

Параметризация связей и аналог коррелированных запросов

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

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

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

Ленивая загрузка и оптимизация запросов к СУБД

Посмотрим на поведение платформы при выводе отчета пользователем. Если мы строим отчет на базе одного огромного запроса со множеством соединений, СУБД всегда выполняет план запроса целиком, обращаясь ко всем соединенным таблицам — даже если пользователь настроил вариант отчета, где поля из половины таблиц вообще не выводятся.

СКД применяет интеллектуальный анализ используемых полей:

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

Гибкость условий связи и язык выражений СКД

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

Это позволяет сопоставлять поля с предварительной обработкой на лету: проверять типы, использовать условные конструкции ВЫБОР, строковые операции и вызовы системных функций без перегрузки текстов базовых запросов сложными преобразованиями.

Повышение читаемости и модульность разработки

Выясним еще одно важное преимущество: сопровождение сложных отчетов. Когда один отчет объединяет учет остатков, взаиморасчеты, данные планирования и плановые цены, написание одного запроса на десятки подзапросов и временных таблиц делает его монолитным и трудночитаемым.

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

  1. Изолировать логику каждого учетного регистра в своем компактном запросе.
  2. Упростить отладку: каждый запрос можно быстро проверить в консоли запросов независимо от остальных.
  3. Упростить параллельную разработку и доработку отчета несколькими программистами без риска разрушить смежные выборки.

Ограничения и нюансы производительности

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

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

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

← На главную