Как эффективно наложить отбор в параметрах виртуальной таблицы в СКД?

Программист 1С v8.3 (Обычные формы) 1С:Управление торговлей Управленческий учет Торговля и дистрибуция
← На главную

При разработке сложных отчетов в системе компоновки данных (СКД), особенно на базе конфигураций типа «Управление торговлей 10.3», часто возникает задача соединения данных о продажах с остатками и резервами. Если просто соединить таблицу оборотов с таблицей остатков через ЛЕВОЕ СОЕДИНЕНИЕ, платформа может сначала получить абсолютно все остатки из базы данных, а уже потом «отсечь» лишние строки при склейке. Это приводит к избыточной нагрузке на сервер и замедлению работы отчета. Рассмотрим, как правильно передавать фильтры в параметры виртуальных таблиц, чтобы ограничить выборку на самом раннем этапе.

Проблема производительности при использовании левых соединений

Разберем типичную ситуацию: в запросе мы обращаемся к регистру Продажи.Обороты и хотим присоединить к нему ТоварыНаСкладах.Остатки. Если не указать условие в параметрах виртуальной таблицы остатков, СУБД выполнит расчет итогов по всем позициям номенклатуры. Даже если в итоговом отчете будет всего 10 строк, система может просканировать тысячи записей в таблицах итогов.

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

Решение 1: Использование временных таблиц и подзапросов

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

  1. Создаем временную таблицу: Выбираем номенклатуру и склады из регистра продаж и помещаем их в ВТ_Продажи.
  2. Индексируем поля: Обязательно индексируем поля Номенклатура и Склад во временной таблице.
  3. Передаем фильтр: В параметрах таблицы остатков используем конструкцию В (ВЫБРАТЬ ... ИЗ ВТ_Продажи).

Пример реализации такого подхода в коде запроса:


// Шаг 1: Получаем базу для отбора
ВЫБРАТЬ РАЗЛИЧНЫЕ
    ПродажиОбороты.Номенклатура КАК Номенклатура,
    ПродажиОбороты.ДокументПродажи.Склад КАК Склад
ПОМЕСТИТЬ ВТ_ДанныеДляОтбора
ИЗ
    РегистрНакопления.Продажи.Обороты(&НачалоПериода, &КонецПериода, , ) КАК ПродажиОбороты
;
////////////////////////////////////////////////////////////////////////////////
// Шаг 2: Получаем остатки с использованием фильтра в параметрах
ВЫБРАТЬ
    ТоварыНаСкладахОстатки.Номенклатура,
    ТоварыНаСкладахОстатки.КоличествоОстаток
ИЗ
    РегистрНакопления.ТоварыНаСкладах.Остатки(&КонецПериода, 
        Номенклатура В (ВЫБРАТЬ Номенклатура ИЗ ВТ_ДанныеДляОтбора)
        И Склад В (ВЫБРАТЬ Склад ИЗ ВТ_ДанныеДляОтбора)
    ) КАК ТоварыНаСкладахОстатки

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

Решение 2: Использование расширения языка запросов СКД

В рамках Системы компоновки данных существует более «красивый» способ, который позволяет платформе автоматически подставлять пользовательские настройки в запрос. Для этого используются фигурные скобки {} в параметрах виртуальной таблицы.

Проанализируем пример конструкции:

РегистрНакопления.ТоварыНаСкладах.Остатки(&КонецПериода, {Номенклатура.*, Склад.*})

Если пользователь в настройках отчета установит отбор по конкретной группе товаров, СКД сама «пробросит» это условие внутрь виртуальной таблицы. Это позволяет СУБД выполнить запрос максимально быстро, обращаясь только к нужным веткам индексов.

Решение 3: Связи наборов данных

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

  1. Создаем первый набор данных (запрос) для получения оборотов продаж.
  2. Создаем второй набор данных (запрос) для получения остатков.
  3. На закладке «Связи наборов данных» указываем связь по полю Номенклатура.
  4. Устанавливаем флаг «Обязательная связь».

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

Важные замечания по индексации

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

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

Для достижения максимальной производительности в СКД придерживайтесь следующих правил:

← На главную