Имя: Пароль:
1C
1С v8
Скорость выполнения запроса
0 slafor
 
02.07.21
13:31
Почему скорость выполнения запроса может резко меняться?

Есть запрос в общем модуле:

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

ЦеныНоменклатурыСрезПоследних
             ЛЕВОЕ СОЕДИНЕНИЕ ЦеныНоменклатурыСрезПоследних КАК ЦеныНоменклатурыСрезПоследних
             ПО (ЦеныНоменклатурыСрезПоследних.Номенклатура = спрНоменклатура.Ссылка)
     ГДЕ
         спрНоменклатура.ПометкаУдаления = ЛОЖЬ
         И спрНоменклатура.ЭтоГруппа = ЛОЖЬ
         И (спрНоменклатура.Остаток <> ЕСТЬNULL(ТоварыНаСкладахОстатки.КоличествоОстаток, 0)
                 ИЛИ спрНоменклатура.Резерв <> ЕСТЬNULL(ТоварыНаСкладахОстатки.РезервОстаток, 0)
                 ИЛИ спрНоменклатура.Цена <> ЕСТЬNULL(ЦеныНоменклатурыСрезПоследних.Цена, 0))

Его суть в следующем: в справочнике Номенклатуры есть доп. реквизиты Остаток, Резерв и Цена, которые перезаполняются при изменении соответствующих данных в регистрах ТоварыНаСкладах и ЦеныНоменклатуры. О вопросе хранения этих данных в самом справочнике я уже советовался в одной из тем этого Форума: Что это - хранение остатков номенклатуры в самом справочнике .

Так вот, в этом запросе мы сверяем значения в реквизитах справочника номенклатура с последними значениями соответствующих данных в регистрах. В моем случае, при первоначальном заполнении, реквизиты, естественно, пустые, поэтому выводятся все элементы справочника - примерно 20000. При следующем запросе (в фоновом режиме или самостоятельно) там может быть 0 или 1-2-3-..., в зависимости от того, у каких элементов справочника эти значения в регистрах изменились.
И вроде бы все логично - при первом заходе запрос должен выполняться дольше. Ан нет. Вчера запустил его на базе, где не было никаких изменений в регистрах - т.е. количество в выборке из результата запроса 0 шт. - а результат запроса получал чуть ли не час. А сегодня заполнил на новой базе с пустыми значениями - в выборке 20000 шт. - и он отработал почти мгновенно. И так каждый раз - вызову его один раз - выполняется сразу, потом перезапускаю базу, вызываю повторно - жду неопределенное время (чуть ли не несколько часов).

От чего это вообще может зависеть?

Еще поясню - в тексте запроса некоторые строки закомментированы. Это потому, что изначально я обращался к регистрам из одного запроса, через ЛЕВОЕ СОЕДИНЕНИЕ с виртуальными таблицами самих регистров, а потом сделал обращения к регистрам во временных таблицах. В общем-то, на скорость выполнения запроса это особо не повлияло...
1 Timon1405
 
02.07.21
14:05
можно попробовать добавить
ИНДЕКСИРОВАТЬ ПО Номенклатура в каждой ВТ
2 zladenuw
 
02.07.21
14:15
и как говорят выше. возьми пакеты номенклатура, товары, цены. соедини потом все всместе.
удали пакеты.
запихни это в соединение
И (спрНоменклатура.Остаток <> ЕСТЬNULL(ТоварыНаСкладахОстатки.КоличествоОстаток, 0)
                 ИЛИ спрНоменклатура.Резерв <> ЕСТЬNULL(ТоварыНаСкладахОстатки.РезервОстаток, 0)
                 ИЛИ спрНоменклатура.Цена <> ЕСТЬNULL(ЦеныНоменклатурыСрезПоследних.Цена, 0))

а так смотреть план запроса скл. что туда полетело.
3 vde69
 
02.07.21
14:16
настроить на sql обновление статистики
4 vde69
 
02.07.21
14:18
ну и еще - не нужно делать временные таблицы в которых нет условий, то есть в принципе не имеют смысла твои временные таблицы
5 Почему 1С
 
02.07.21
14:23
(4) тут соглашусь, но 1С дала рекомендации избегать соединений с виртуальными таблицами, вот народ и избегает
6 Малыш Джон
 
02.07.21
14:23
(4)  
Cоединения с виртуальными таблицами
Рекомендации
Если в запросе используется соединение с виртуальной таблицей языка запросов 1С:Предприятия (например, "РегистрНакопления.Товары.Остатки()") и запрос работает с неудовлетворительной производительностью, то рекомендуется вынести обращение к виртуальной таблице в отдельный запрос с сохранением результатов во временной таблице.

https://its.1c.ru/db/metod8dev/content/5842/hdoc
7 Почему 1С
 
02.07.21
14:31
(0) Я бы сделал следующее, подключил систему замера производительности ключевыми операциями бы разбил запрос на части и сам запрос целиком. Ну и провел замеров 50, думаю картина стала бы яснее
8 Малыш Джон
 
02.07.21
14:44
Я б для начала в консоль запрос вытащил бы и проверил как он отрабатывает. Сдается мне, не в запросе дело, а в контексте выполнения.
9 slafor
 
02.07.21
15:01
(8) Вот это очень даже может быть. Потому что если один и тот же запрос выполняется с разной производительностью... и от того, сколько там данных в результате, мало зависит время выполнения запроса... Попробую в консоли запросов, спасибо.
10 slafor
 
03.07.21
02:24
(1) Да, добавление ИНДЕКСИРОВАТЬ ПО в ВТ очень даже помогло.

Но скорее всего, проблемы возникали из-за простой невнимательности - как оказалось, эта процедура с запросом из общего модуля вызывалась как из внешней обработки, так и из фонового задания. И это могло происходить одновременно. Так что все поправил, все работает. Всем спасибо )