Имя: Пароль:
1C
1С v8
Помогите оптимизировать запрос для получения остатков и цен номенклатуры
0 Boudybuilder
 
23.10.13
23:38
Всем доброго вечера!

Работаю на рабочим столом менеджера по продажам. Есть поле "ДеревоНоменклатуры" ТипЗначения:СправочникСписок.Номенклатура , только группы. Оно служит для навигации. При активации строки выполняется запрос , и все элементы попадают в табличную часть , откуда я уже подбираю в заказ. Все бы хорошо , но запрос долго выполняется,  особенно первое выполнение запроса. Пока не закешируется. Вопрос в том , как бы тут его оптимизировать. Или как подскажете сделать по другому. Вот запрос:





ВЫБРАТЬ РАЗРЕШЕННЫЕ
    ВЗ_Товары.КоличествоОстаток,
    ВЗ_Товары.ХарактеристикаНоменклатуры КАК ХарактеристикаНоменклатуры,
    Цены.ЕдиницаИзмерения,
    Цены.Цена * Курсы.Курс / Курсы.Кратность / КурсВалютыВзаиморасчетов.Курс * КурсВалютыВзаиморасчетов.Кратность КАК Цена,
    ВЗ_Товары.Номенклатура КАК Номенклатура,
    ВЗ_Товары.Номенклатура.ДатаСоздания КАК ДатаСоздания
ИЗ
    (ВЫБРАТЬ
        ТоварыНаСкладахОстатки.КоличествоОстаток КАК КоличествоОстаток,
        ТоварыНаСкладахОстатки.ХарактеристикаНоменклатуры КАК ХарактеристикаНоменклатуры,
        ТоварыНаСкладахОстатки.Номенклатура КАК Номенклатура
    ИЗ
        РегистрНакопления.ТоварыНаСкладах.Остатки(
                ,
                Номенклатура.Родитель = &Родитель
                    ИЛИ Номенклатура.Родитель.Родитель = &Родитель) КАК ТоварыНаСкладахОстатки
    
    ОБЪЕДИНИТЬ ВСЕ
    
    ВЫБРАТЬ
        ТоварыВРозницеОстатки.КоличествоОстаток,
        ТоварыВРозницеОстатки.ХарактеристикаНоменклатуры,
        ТоварыВРозницеОстатки.Номенклатура
    ИЗ
        РегистрНакопления.ТоварыВРознице.Остатки(
                ,
                Номенклатура.Родитель = &Родитель
                    ИЛИ Номенклатура.Родитель.Родитель = &Родитель) КАК ТоварыВРозницеОстатки
    
    ОБЪЕДИНИТЬ ВСЕ
    
    ВЫБРАТЬ
        ТоварыВНТТОстатки.КоличествоОстаток,
        ТоварыВНТТОстатки.ХарактеристикаНоменклатуры,
        ТоварыВНТТОстатки.Номенклатура
    ИЗ
        РегистрНакопления.ТоварыВНТТ.Остатки(
                ,
                Номенклатура.Родитель = &Родитель
                    ИЛИ Номенклатура.Родитель.Родитель = &Родитель) КАК ТоварыВНТТОстатки) КАК ВЗ_Товары
        ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ЦеныНоменклатуры.СрезПоследних(, ТипЦен = &ТипЦены) КАК Цены
            ВНУТРЕННЕЕ СОЕДИНЕНИЕ РегистрСведений.КурсыВалют.СрезПоследних(, ) КАК Курсы
            ПО Цены.Валюта = Курсы.Валюта
        ПО ВЗ_Товары.ХарактеристикаНоменклатуры = Цены.ХарактеристикаНоменклатуры
            И ВЗ_Товары.Номенклатура = Цены.Номенклатура,
    РегистрСведений.КурсыВалют.СрезПоследних(, Валюта = &Валюта) КАК КурсВалютыВзаиморасчетов

УПОРЯДОЧИТЬ ПО
    Номенклатура,
    Цена
1 Boudybuilder
 
23.10.13
23:38
Да , и упорядовачивание почему то игнорируется...
2 Armando
 
23.10.13
23:46
Во первых, соединение со срезом последних узкое место.
3 Armando
 
23.10.13
23:48
Номенклатура.Родитель = &Родитель ИЛИ Номенклатура.Родитель.Родитель = &Родитель
тоже не очень
4 Boudybuilder
 
23.10.13
23:52
Срез последних в ВТ загонять и так соединять?
5 Armando
 
23.10.13
23:52
Срезы по курсам и ценам можно выполнить один раз при открытии формы, поместить во временную таблицу. И каждый раз брать уже оттуда
6 Boudybuilder
 
23.10.13
23:52
(3) А тут тогда как быть?
Надо же по родителю отбирать...
7 Boudybuilder
 
23.10.13
23:53
(5) О! ) Думаю хорошо будет.
8 Armando
 
23.10.13
23:57
(6) у тебя (3) выполняется 3 раза. Можно отдельным пакетом выбрать номенклатуру, поместить в ВТ и в параметрах виртуальной таблицы прописывать условие по номенклатуре из этой ВТ
9 Armando
 
23.10.13
23:58
(1) воткни флаг автоупорядочивание
10 Boudybuilder
 
24.10.13
00:03
(8) Я думал что лучше сразу отбор делать в ВиртуальнойТаблице чем получать данные по всем трем запросам , и их уже отбирать.
11 Boudybuilder
 
24.10.13
00:06
(8) Ну вот...
Вынес условие , и запрос дольше выполняется
12 romansun
 
24.10.13
00:06
имхо трижды Родители вот эти через стопятьсот точек в параметрах виртуальной таблицы сводят скуль с ума

отбери нужную тебе номенклатуру один раз в ВТ... как в (8) посоветовали, да. Должно помочь, ибо в остальном каких-то прям явно видимых косяков вроде нет. Ну, курсы еще, да
13 romansun
 
24.10.13
00:08
(11)

))))

вынеси всё номенклатуру в ВТ и запускай запросы по одному, два остальных заремарь. Отследи какой запрос больше всего затыкается.
14 Armando
 
24.10.13
00:09
(10) не, что-то типа такого должно получиться:
выбрать Ссылка
поместить ВТ_Номенклатура
из Справочник.Номенклатура
где ....
;
выбрать * из РегистрНакопления.ТоварыНаСкладах.Остатки(, Номенклатура в (выбрать Ссылка из ВТ_Номенклатура))
15 romansun
 
24.10.13
00:11
+ если есть где в условиях джоинов многотиповые поля - их надо типизировать принудительно к нужному типу обязательно

"ХарактеристикаНоменклатуры" не такое? Я просто хз, что там, да как..
16 Armando
 
24.10.13
00:16
(15) думаю в данном случае нет смысла, т.к. нет получения полей через точку.
17 Boudybuilder
 
24.10.13
00:25
(8) Это как ?
Можно пример?
18 Armando
 
24.10.13
00:29
(17) см (14)
19 ViSo76
 
24.10.13
00:41
За таки запросы можно сразу расстреливать на месте без суда и следствия :)
20 Boudybuilder
 
24.10.13
00:45
|ГДЕ
                   |    ВЗ_Товары.Номенклатура В ИЕРАРХИИ(&Родитель)

Это значительно помогло.
Немного изменилась суть результата , но это не так важно...
21 Boudybuilder
 
24.10.13
00:45
(19) Это еще что , я новичком запросы в циклах делал )))
22 Boudybuilder
 
24.10.13
00:46
(19) Стреляй! Не промахнешься... )))
23 Armando
 
24.10.13
00:47
(19) за флуд в тематической ветке тоже
24 ViSo76
 
24.10.13
00:57
Хорошо вопрос на засыпку кто скажет как будет выполнен данный кусок запроса?

РегистрНакопления.ТоварыНаСкладах.Остатки(
                ,
                Номенклатура.Родитель = &Родитель
                    ИЛИ Номенклатура.Родитель.Родитель = &Родитель)
25 Boudybuilder
 
24.10.13
00:58
(24) Серьезные люди присоединились ;)
26 Armando
 
24.10.13
01:11
(24) через 2 левых и что?
27 ViSo76
 
24.10.13
01:22
А будет вот что, в начале будут получены все ближайшие остатки + движения до последнего изменения, т.к. открытый период то и захватит к примеру приход через неделю, далее идёт не два соединения а 3 соединения с фильтрацией. Это не оптимально, было бы лучше получить остатки не для всех позиций, а только для необходимой номенклатуры, вот так ( пишу запрос в блакноте так что если будут ошибки поправьте ):

ВЫБРАТЬ
    Ссылка КАК Номенклатура,
    Родитель

ПОМЕСТИТЬ тзВсяНоменклатура

ИЗ
    Справочник.Номенклатура
ГДЕ
    Ссылка В ИЕРАРХИИ( &Родитель )
;

ВЫБРАТЬ
    Ссылка

ПОМЕСТИТЬ тзСписокНоменклатурыДляФильтрации

ИЗ
    тзВсяНоменклатура
ГДЕ
    Родитель = &Родитель

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
    тзВсяНоменклатура.Ссылка
ИЗ
    тзВсяНоменклатура

    СОЕДИНЕНИЕ Справочник.Номенклатура КАК спрНоменклатура
        ПО спрНоменклатура.Ссылка = тзВсяНоменклатура.Родитель
         И спрНоменклатура.Родитель = &Родитель

// Сделал явное соединение чтобы разжевать неявное соединение закоментированное ниже
//ГДЕ
//    Родитель.Родитель = &Родитель
;

УНИЧТОЖИТЬ тзВсяНоменклатура;


ВЫБРАТЬ
        Номенклатура,
        ХарактеристикаНоменклатуры,
        СУММА( КоличествоОстаток ) КАК КоличествоОстаток

//ПОМЕСТИТЬ тзОстатки

ИЗ
    ( ВЫБРАТЬ
        Номенклатура,
        ХарактеристикаНоменклатуры,
        КоличествоОстаток
        ИЗ
        РегистрНакопления.ТоварыНаСкладах.Остатки( , Номенклатура В ( ВЫБРАТЬ Ссылка ИЗ тзСписокНоменклатурыДляФильтрации ) )

            ОБЪЕДИНИТЬ ВСЕ
    
        ВЫБРАТЬ
        Номенклатура,
        ХарактеристикаНоменклатуры,
        КоличествоОстаток
    ИЗ
        РегистрНакопления.ТоварыВРознице.Остатки( , Номенклатура В ( ВЫБРАТЬ Ссылка ИЗ тзСписокНоменклатурыДляФильтрации ) )
    
    ОБЪЕДИНИТЬ ВСЕ
    
    ВЫБРАТЬ
        Номенклатура,
        ХарактеристикаНоменклатуры,
        КоличествоОстаток
    ИЗ
        РегистрНакопления.ТоварыВНТТ.Остатки( , Номенклатура В ( ВЫБРАТЬ Ссылка ИЗ тзСписокНоменклатурыДляФильтрации ) )

    ) КАК втОстатки

СГРУППИРОВАТЬ ПО
    Номенклатура,
    ХарактеристикаНоменклатуры
;

Далее естественно срез последних так же идёт для всех номенклатур что тоже не является оптимальным...

Вопрос на засыпку что нужно сделать далее?
28 Boudybuilder
 
24.10.13
01:40
(27) Проверил свой запрос в УКЗ  на скорость и твой...
Разницы никакой!!!!
29 Armando
 
24.10.13
01:42
(27) >> А будет вот что, в начале будут получены все ближайшие остатки + движения до последнего изменения, т.к. открытый период то и захватит к примеру приход через неделю, далее идёт не два соединения а 3 соединения с фильтрацией

Не так. Просто будут получены остатки на какую-то большую дату, типа 3999 год. И 2 соединения с Номенклатурой.
30 viktor_vv
 
24.10.13
02:34
А вот это

"и все элементы попадают в табличную часть"

табличная часть - это что ? Табличное поле с источником данных таблица значений?

Лучше так сделать. Оставляешь дерево групп для навигации. Вешаешь на форму табличное поле с источником СправочникСписок.
При активизации строки дерева накладываешь отбор на список по Ссылка с условием ВГруппе. А остатки и цены выгребаешь в ПриВыводеСтроки() списка (простое условие по конкретной номенклатуре) или ПриПолученииДанных() (немного сложнее условие по массиву ссылок, но проще чем твои через несколько точек).
31 viktor_vv
 
24.10.13
02:39
(30)+ У тебя в группе может быть десяток тысяч позиций номенклатуры, нафига тебе тащить остатки и цены по ним всем при активации группы, да еще и с таким тяжелым условием в параметрах, если на экран влезет максимум 50-100, вот по ним и тащи.
32 Boudybuilder
 
24.10.13
03:08
ВЫБРАТЬ РАЗРЕШЕННЫЕ
    Номенклатура.Ссылка
ПОМЕСТИТЬ ВТ_ВГруппе
ИЗ
    Справочник.Номенклатура КАК Номенклатура
ГДЕ
    Номенклатура.Родитель В ИЕРАРХИИ(&Родитель)
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ РАЗРЕШЕННЫЕ
    ТоварыНаСкладахОстатки.КоличествоОстаток КАК КоличествоОстаток,
    ТоварыНаСкладахОстатки.ХарактеристикаНоменклатуры КАК ХарактеристикаНоменклатуры,
    ТоварыНаСкладахОстатки.Номенклатура КАК Номенклатура
ПОМЕСТИТЬ ВТ_Остатки
ИЗ
    РегистрНакопления.ТоварыНаСкладах.Остатки(
            ,
            Номенклатура В
                (ВЫБРАТЬ
                    ВТ_ВГруппе.Ссылка
                ИЗ
                    ВТ_ВГруппе)) КАК ТоварыНаСкладахОстатки

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
    ТоварыВРозницеОстатки.КоличествоОстаток,
    ТоварыВРозницеОстатки.ХарактеристикаНоменклатуры,
    ТоварыВРозницеОстатки.Номенклатура
ИЗ
    РегистрНакопления.ТоварыВРознице.Остатки(
            ,
            Номенклатура В
                (ВЫБРАТЬ
                    ВТ_ВГруппе.Ссылка
                ИЗ
                    ВТ_ВГруппе)) КАК ТоварыВРозницеОстатки

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
    ТоварыВНТТОстатки.КоличествоОстаток,
    ТоварыВНТТОстатки.ХарактеристикаНоменклатуры,
    ТоварыВНТТОстатки.Номенклатура
ИЗ
    РегистрНакопления.ТоварыВНТТ.Остатки(
            ,
            Номенклатура В
                (ВЫБРАТЬ
                    ВТ_ВГруппе.Ссылка
                ИЗ
                    ВТ_ВГруппе)) КАК ТоварыВНТТОстатки
;

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

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
    ВТ_ОстаткиИЦены.Номенклатура КАК Номенклатура,
    ВТ_ОстаткиИЦены.ХарактеристикаНоменклатуры,
    ВТ_ОстаткиИЦены.ЕдиницаИзмерения,
    ВТ_ОстаткиИЦены.Цена * Курсы.Курс / Курсы.Кратность / КурсВалютыВзаиморасчетов.Курс * КурсВалютыВзаиморасчетов.Кратность КАК Цена,
    ВТ_ОстаткиИЦены.Номенклатура.ДатаСоздания КАК ДатаСоздания
ИЗ
    ВТ_ОстаткиИЦены КАК ВТ_ОстаткиИЦены
        ВНУТРЕННЕЕ СОЕДИНЕНИЕ РегистрСведений.КурсыВалют.СрезПоследних КАК Курсы
        ПО ВТ_ОстаткиИЦены.Валюта = Курсы.Валюта,
    РегистрСведений.КурсыВалют.СрезПоследних(, Валюта = &Валюта) КАК КурсВалютыВзаиморасчетов

УПОРЯДОЧИТЬ ПО
    Номенклатура,
    Цена
АВТОУПОРЯДОЧИВАНИЕ



Работает в 100 раз быстрее , + 1С не зависает при его выполнении
33 Armando
 
24.10.13
07:48
Будет еще быстрее, если сделаешь (5)

Зачем здесь еще один срез, тем более без соединения:
"ИЗ
    ВТ_ОстаткиИЦены КАК ВТ_ОстаткиИЦены
        ВНУТРЕННЕЕ СОЕДИНЕНИЕ РегистрСведений.КурсыВалют.СрезПоследних КАК Курсы
        ПО ВТ_ОстаткиИЦены.Валюта = Курсы.Валюта,
    РегистрСведений.КурсыВалют.СрезПоследних(, Валюта = &Валюта) КАК КурсВалютыВзаиморасчетов"

Вот это тоже не понял
ВТ_ОстаткиИЦены.Цена * Курсы.Курс / Курсы.Кратность / КурсВалютыВзаиморасчетов.Курс * КурсВалютыВзаиморасчетов.Кратность КАК Цена,
34 Sammo
 
24.10.13
08:06
(32) Я бы таки попробовал номенклатуру убрать из параметра виртуальной таблицы и сделать внутреннее с ВТ_ВГруппе
Это скорее всего не первое измерение, размер выборки может быть большой.
35 Sammo
 
24.10.13
08:10
Цены тоже не через В а через соединение.
36 ViSo76
 
24.10.13
08:20
(28) А ты проверил вместе с соединением срез последних? Конечно никакой разницы ты не почувствуешь, т.к. я только часть кода привёл. Получение цены разумеется нужно делать так:

ВЫБРАТЬ
    Номенклатура,
    ХарактеристикаНоменклатуры,
    Цена
ИЗ
    РегистрСведений.ЦеныНоменклатуры.СрезПоследних(, ТипЦен = &ТипЦены И ХарактеристикаНоменклатуры В ( ВЫБРАТЬ РАЗЛИЧНЫЕ Номенклатура ИЗ тзОстатки ) И ХарактеристикаНоменклатуры В ( ВЫБРАТЬ ХарактеристикаНоменклатуры ИЗ тзОстатки ) )

А то самое тормознутое оставил и радуется что не помогло...

И мой запрос будет работать быстрее по тому что изначально номенклатуры может быть меньше и после получения остатков номенклатуры может ещё стать меньше и количество цен соответственно будет вычислено меньше...

PS: Остальную часть запроса я предлагал написать вам...
Я не хочу быть самым богатым человеком на кладбище. Засыпать с чувством, что за день я сделал какую-нибудь потрясающую вещь — вот что меня интересует. Стив Джобс