При разработке сложных отчетов в системе компоновки данных (СКД), особенно на базе конфигураций типа «Управление торговлей 10.3», часто возникает задача соединения данных о продажах с остатками и резервами. Если просто соединить таблицу оборотов с таблицей остатков через ЛЕВОЕ СОЕДИНЕНИЕ, платформа может сначала получить абсолютно все остатки из базы данных, а уже потом «отсечь» лишние строки при склейке. Это приводит к избыточной нагрузке на сервер и замедлению работы отчета. Рассмотрим, как правильно передавать фильтры в параметры виртуальных таблиц, чтобы ограничить выборку на самом раннем этапе.
Разберем типичную ситуацию: в запросе мы обращаемся к регистру Продажи.Обороты и хотим присоединить к нему ТоварыНаСкладах.Остатки. Если не указать условие в параметрах виртуальной таблицы остатков, СУБД выполнит расчет итогов по всем позициям номенклатуры. Даже если в итоговом отчете будет всего 10 строк, система может просканировать тысячи записей в таблицах итогов.
Многие разработчики ошибочно полагают, что секция ГДЕ или условие связи ПО эффективно фильтруют данные. Однако для виртуальных таблиц критически важно передавать условия именно в параметры (второй параметр для таблиц остатков), так как это позволяет платформе использовать индексы физических таблиц итогов.
Один из самых надежных способов для классических запросов — сначала подготовить список нужных товаров во временной таблице, а затем использовать этот список в параметрах последующих виртуальных таблиц. Разберем по шагам, как это реализовать:
ВТ_Продажи.Номенклатура и Склад во временной таблице.В (ВЫБРАТЬ ... ИЗ ВТ_Продажи).Пример реализации такого подхода в коде запроса:
// Шаг 1: Получаем базу для отбора
ВЫБРАТЬ РАЗЛИЧНЫЕ
ПродажиОбороты.Номенклатура КАК Номенклатура,
ПродажиОбороты.ДокументПродажи.Склад КАК Склад
ПОМЕСТИТЬ ВТ_ДанныеДляОтбора
ИЗ
РегистрНакопления.Продажи.Обороты(&НачалоПериода, &КонецПериода, , ) КАК ПродажиОбороты
;
////////////////////////////////////////////////////////////////////////////////
// Шаг 2: Получаем остатки с использованием фильтра в параметрах
ВЫБРАТЬ
ТоварыНаСкладахОстатки.Номенклатура,
ТоварыНаСкладахОстатки.КоличествоОстаток
ИЗ
РегистрНакопления.ТоварыНаСкладах.Остатки(&КонецПериода,
Номенклатура В (ВЫБРАТЬ Номенклатура ИЗ ВТ_ДанныеДляОтбора)
И Склад В (ВЫБРАТЬ Склад ИЗ ВТ_ДанныеДляОтбора)
) КАК ТоварыНаСкладахОстатки
Несмотря на то, что имя временной таблицы нельзя передать в параметр напрямую как переменную, использование подзапроса внутри скобок параметра является допустимым и эффективным методом.
В рамках Системы компоновки данных существует более «красивый» способ, который позволяет платформе автоматически подставлять пользовательские настройки в запрос. Для этого используются фигурные скобки {} в параметрах виртуальной таблицы.
Проанализируем пример конструкции:
РегистрНакопления.ТоварыНаСкладах.Остатки(&КонецПериода, {Номенклатура.*, Склад.*})
Если пользователь в настройках отчета установит отбор по конкретной группе товаров, СКД сама «пробросит» это условие внутрь виртуальной таблицы. Это позволяет СУБД выполнить запрос максимально быстро, обращаясь только к нужным веткам индексов.
Если запрос получается слишком сложным и громоздким, мы можем разделить его на несколько наборов данных в схеме компоновки. Рассмотрим этот алгоритм:
Номенклатура.В этом случае СКД будет передавать список номенклатуры из первого набора в параметры второго набора динамически. Для оптимизации выполнения запроса по связи важно, чтобы во втором наборе данных в параметрах виртуальной таблицы также были указаны соответствующие поля в фигурных скобках.
Посмотрим на ситуацию с точки зрения производительности СУБД. Индексы на самих виртуальных таблицах не строятся динамически во время выполнения запроса. Однако грамотная индексация временных таблиц помогает ускорить операцию JOIN (соединение). Если вы используете пакетный запрос, всегда индексируйте поля, по которым происходит связь. Как показывают замеры (статистика RecordsScanned), при работе с большими объемами данных разница в количестве просканированных записей между запросом с отбором в параметрах и без него может быть десятикратной.
Для достижения максимальной производительности в СКД придерживайтесь следующих правил:
ГДЕ.{} для автоматизации передачи пользовательских фильтров.