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

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

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

Рассмотрим подробнее оба варианта, проанализируем механизмы их работы «под капотом» и выясним, в каких ситуациях каждый из них будет наиболее эффективным.

Вариант 1: Левое соединение в одном наборе данных (запросе)

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

Преимущества единого запроса:

  1. Оптимизация на стороне СУБД: Когда мы используем ЛЕВОЕ СОЕДИНЕНИЕ внутри одного запроса, планировщик SQL-сервера видит всю структуру целиком. Он может проанализировать индексы всех участвующих таблиц и выбрать оптимальный план выполнения (например, использование Hash Join или Merge Join).
  2. Минимизация количества обращений к базе: В этом случае 1С отправляет в СУБД ровно один запрос. Это критично при работе в клиент-серверном варианте, так как исключаются лишние сетевые задержки между сервером приложений и сервером баз данных.
  3. Эффективная фильтрация: Пользовательские отборы, установленные в настройках отчета, СКД автоматически транслирует в секцию ГДЕ (WHERE) итогового SQL-запроса. Это позволяет СУБД отсечь ненужные данные на самом раннем этапе, не выкачивая лишние строки в память сервера приложений.

Главная проблема: «Задвоение» итогов

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

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


ВЫБРАТЬ
    ТоварыНаСкладах.Номенклатура,
    СУММА(ТоварыНаСкладах.В наличии) КАК Количество,
    Характеристики.Цвет
ИЗ
    РегистрНакопления.ТоварыНаСкладах.Остатки КАК ТоварыНаСкладах
ЛЕВОЕ СОЕДИНЕНИЕ Справочник.Характеристики КАК Характеристики
    ПО ТоварыНаСкладах.Номенклатура = Характеристики.Владелец
СГРУППИРОВАТЬ ПО
    ТоварыНаСкладах.Номенклатура,
    Характеристики.Цвет

Вариант 2: Связи наборов данных в СКД

Использование нескольких наборов данных (Набор1, Набор2) и их соединение через вкладку «Связи наборов данных» работает принципиально иначе. Здесь соединение происходит не на уровне SQL, а на уровне сервера приложений 1С.

Почему это может быть удобно и полезно:

  1. Корректный расчет ресурсов: Это главный аргумент «ЗА». СКД умеет вычислять итоги для каждого набора данных независимо. Если у вас в первом наборе остатки, а во втором — детальные записи, то при их связи суммы по первому набору не будут «размножаться», сколько бы строк ни пришло из второго набора. Система сама сопоставит данные на уровне вывода компоновки.
  2. Связь данных из разных источников: Это единственный способ, если вам нужно соединить данные из стандартного запроса к базе и, например, внешней ТаблицыЗначений или данных, полученных через Объектный набор данных.
  3. Сложные параметрические связи: Рассмотрим ситуацию, когда нам нужно получить «Срез последних» на каждую дату из основного запроса. В обычном запросе это решается крайне тяжело и медленно. В связях наборов данных мы можем передать поле Период из первого набора в параметр второго набора.

Риски и недостатки связей наборов:

  1. Проблема «N+1» запросов: Если связь настроена по параметрам, 1С может начать выполнять отдельный запрос ко второму набору для каждой строки первого набора. Если в первом наборе 10 000 строк, вы получите 10 001 запрос к базе данных, что мгновенно «положит» производительность.
  2. Нагрузка на память сервера приложений: Так как соединение таблиц происходит «в памяти» 1С, при больших объемах данных (сотни тысяч строк) сервер приложений может столкнуться с нехваткой оперативной памяти. SQL-сервер гораздо эффективнее управляет большими объемами данных при соединениях.
  3. Неоптимальные отборы: Если пользователь установит отбор по полю из второго (дочернего) набора, СКД может сначала получить все данные из первого набора, и только потом применить фильтр, что приведет к избыточному трафику между СУБД и сервером 1С.

Сравнение механизмов индексации

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


ВЫБРАТЬ Номенклатура, Склад ПОМЕСТИТЬ ВТ_Остатки ИНДЕКСИРОВАТЬ ПО Номенклатура ИЗ ... ;
ВЫБРАТЬ Ссылка, Цвет ПОМЕСТИТЬ ВТ_Свойства ИНДЕКСИРОВАТЬ ПО Ссылка ИЗ ... ;
ВЫБРАТЬ * ИЗ ВТ_Остатки ЛЕВОЕ СОЕДИНЕНИЕ ВТ_Свойства ПО ВТ_Остатки.Номенклатура = ВТ_Свойства.Ссылка;

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

Практические рекомендации: что выбрать?

Разберем типичные ситуации для выбора того или иного метода:

Заключение

Нельзя сказать, что один метод однозначно лучше другого. Левое соединение в запросе — это инструмент для работы с «большими данными» и обеспечения производительности на уровне СУБД. Связи наборов данных — это мощный механизм сервера приложений для решения сложных логических задач и корректного агрегирования данных из разнородных источников. Проанализируйте характер ваших данных и требования к итогам отчета перед тем, как принять окончательное решение.

← На главную