1С 8.3. Как оптимизировать данный код? Долго грузится

Рейтинг: 0Ответов: 1Опубликовано: 14.03.2023

Есть такой код:

Запрос = Новый Запрос;
    Запрос.Текст = "ВЫБРАТЬ
    | РегистрНакопленияПартииТоваров.Номенклатура Как Номенклатура,
    | СУММА(РегистрНакопленияПартииТоваров.Количество) Как Количество,    
    | МАКСИМУМ(ЕСТЬNULL(УчетНоменклатурыОстатки.КоличествоОстаток, 0)) КАК КоличествоОстаток,    
    | МАКСИМУМ(ЕСТЬNULL(РегистрНакопленияПартииТоваров.СуммаУпр, 0)) КАК СебестоимостьУпр,
    | МАКСИМУМ(ЕСТЬNULL(ПартииТоваровКомпанииОстаткиИОбороты.КоличествоРасход, 0)) КАК КоличествоРасход,
    | МАКСИМУМ(ЕСТЬNULL(ПартииТоваровКомпанииОстаткиИОборотыНеделя.КоличествоРасход, 0)) КАК КоличествоРасходНеделя
    |ИЗ                           
    | РегистрНакопления.ПартииТоваровКомпании КАК РегистрНакопленияПартииТоваров 
    
    |     ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ОстаткиТоваровКомпании.Остатки КАК УчетНоменклатурыОстатки
    |     ПО УчетНоменклатурыОстатки.Номенклатура.Артикул = РегистрНакопленияПартииТоваров.Номенклатура.Артикул
    
    |     ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ПартииТоваровКомпании.ОстаткиИОбороты(&НачПериода,&КонецПериода) КАК ПартииТоваровКомпанииОстаткиИОбороты
    |     ПО ПартииТоваровКомпанииОстаткиИОбороты.Номенклатура.Артикул = РегистрНакопленияПартииТоваров.Номенклатура.Артикул
    
    |     ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ПартииТоваровКомпании.ОстаткиИОбороты(&НачПериодаНеделя,&КонецПериодаНеделя) КАК ПартииТоваровКомпанииОстаткиИОборотыНеделя
    |     ПО ПартииТоваровКомпанииОстаткиИОборотыНеделя.Номенклатура.Артикул = РегистрНакопленияПартииТоваров.Номенклатура.Артикул
    
    |ГДЕ РегистрНакопленияПартииТоваров.Период МЕЖДУ НАЧАЛОПЕРИОДА(&НачалоДаты) И КОНЕЦПЕРИОДА(&КонецДаты) И
    |РегистрНакопленияПартииТоваров.ХозОперация = &ХозОперация
    
    |СГРУППИРОВАТЬ ПО РегистрНакопленияПартииТоваров.Номенклатура";
    
    Запрос.УстановитьПараметр("НачалоДаты",ДатаНачала);
    Запрос.УстановитьПараметр("КонецДаты",ДатаОкончания);
    
    Запрос.УстановитьПараметр("НачПериода", ДобавитьМесяц(ТекущаяДата(), -12) ); 
    Запрос.УстановитьПараметр("КонецПериода",ТекущаяДата());
    Запрос.УстановитьПараметр("ХозОперация",Справочники.ХозОперации.НайтиПоНаименованию("Перемещение товаров в производство"));
    
    Запрос.УстановитьПараметр("НачПериодаНеделя", ТекущаяДата()-60*60*24*7 ); 
    Запрос.УстановитьПараметр("КонецПериодаНеделя",ТекущаяДата());

    
    ТаблицаОтчета = Запрос.Выполнить().Выбрать();

Код начал долго грузиться после добавления еще одного левого соединения:

ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ПартииТоваровКомпании.ОстаткиИОбороты(&НачПериодаНеделя,&КонецПериодаНеделя) КАК ПартииТоваровКомпанииОстаткиИОборотыНеделя
    ПО ПартииТоваровКомпанииОстаткиИОборотыНеделя.Номенклатура.Артикул = РегистрНакопленияПартииТоваров.Номенклатура.Артикул

Как оптимизировать данный код?

Точнее вот эти две левые соединении (можно ли их как-то объединить, но чтобы параметры периодов были разными):

ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ПартииТоваровКомпании.ОстаткиИОбороты(&НачПериода,&КонецПериода) КАК ПартииТоваровКомпанииОстаткиИОбороты
ПО ПартииТоваровКомпанииОстаткиИОбороты.Номенклатура.Артикул = РегистрНакопленияПартииТоваров.Номенклатура.Артикул

ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ПартииТоваровКомпании.ОстаткиИОбороты(&НачПериодаНеделя,&КонецПериодаНеделя) КАК ПартииТоваровКомпанииОстаткиИОборотыНеделя
ПО ПартииТоваровКомпанииОстаткиИОборотыНеделя.Номенклатура.Артикул = РегистрНакопленияПартииТоваров.Номенклатура.Артикул

Ответы

▲ 0Принят

1 - Остатки нужно получать на определенную дату

 ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ОстаткиТоваровКомпании.Остатки(&НаДату) КАК УчетНоменклатурыОстатки

2 - Условие соединения следует проверить, - точно .Номенклатура.Артикул ?! Если Артикулы номенклатуры не ведутся, достаточно соединить по Номенклатура

ПО УчетНоменклатурыОстатки.Номенклатура = РегистрНакопленияПартииТоваров.Номенклатура

Если Артикулы ведутся тогда, для подстраховки я бы использовал (чтобы исключить ситуацию когда у разной номенклатуры одинаковый артикул)

    ПО УчетНоменклатурыОстатки.Номенклатура = РегистрНакопленияПартииТоваров.Номенклатура 
И УчетНоменклатурыОстатки.Номенклатура.Артикул = РегистрНакопленияПартииТоваров.Номенклатура.Артикул

3 - Условие соединения следует использовать во всех соединениях.

4 - МАКСИМУМ() нужно убрать* (при использовании оптимизации, в исходном запросе имеет определенный смысл)

5 - Если стоит задача оптимизации запроса в целом, - желательно использовать временные таблицы; Это не простая задача, но в общих чертах можно сказать следующее:

    ВЫБРАТЬ
     РегистрНакопленияПартииТоваров.Номенклатура Как Номенклатура,
     СУММА(РегистрНакопленияПартииТоваров.Количество) Как Количество
    ПОМЕСТИТЬ ВТ
    СГРУППИРОВАТЬ ПО РегистрНакопленияПартииТоваров.Номенклатура
    
    ;
    
    ВЫБРАТЬ Номенклатура 
    ПОМЕСТИТЬ ВТ_Номенклатура 
    ИЗ ВТ
    ИНДЕКСИРОВАТЬ ПО Номенклатура
    ;  // Сформируем список Номенклатуры
    
    ВЫБРАТЬ 
     ВТ.Номенклатура,
     ВТ.Количество,
     ЕСТЬNULL(УчетНоменклатурыОстатки_.КоличествоОстаток, 0) КАК КоличествоОстаток
    ИЗ ВТ
     ЛЕВОЕ СОЕДИНЕНИЕ (ВЫБРАТЬ УчетНоменклатурыОстатки.КоличествоОстаток КАК КоличествоОстаток,
УчетНоменклатурыОстатки.Номенклатура КАК Номенклатура
       ИЗ РегистрНакопления.ОстаткиТоваровКомпании.Остатки(&НаДату) КАК УчетНоменклатурыОстатки 
    ГДЕ УчетНоменклатурыОстатки.Номенклатура В (ВТ_Номенклатура)) КАК  УчетНоменклатурыОстатки_
         ПО УчетНоменклатурыОстатки_.Номенклатура = ВТ.Номенклатура 
    
    // Остальные ЛЕВОЕ СОЕДИНЕНИЕ следует описать аналогичным образом;