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