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