Имя: Пароль:
1C
1С v8
Запрос. Перенос условия из ГДЕ в параметры ВТ дает замедление
0 cons74
 
01.07.16
21:22
В типичных причинах неоптимальных запросов (https://its.1c.ru/db/metod8dev#content:5842:hdoc) рекомендуется условия на виртуальные таблицы накладывать в параметрах, а не в ГДЕ.
В моем же примере это дает замедление 30-40%. Почему?

"Быстрый запрос"

///////////////////////////////////////////////////////////////////
ВЫБРАТЬ
    НАЧАЛОПЕРИОДА(ПродажиОбороты.ДокументПродажи.Дата, ДЕНЬ) КАК ДатаДок,
    ВЫБОР
        КОГДА НЕ &ОтсрочкаПоСрокамГодностиТовара
            ТОГДА 0
        ИНАЧЕ ВЫБОР
                КОГДА ПродажиОбороты.Номенклатура.СрокГодностиТовара.КоличествоСуток < 10
                    ТОГДА 1
                ИНАЧЕ ВЫБОР
                        КОГДА ПродажиОбороты.Номенклатура.СрокГодностиТовара.КоличествоСуток >= 10
                                И ПродажиОбороты.Номенклатура.СрокГодностиТовара.КоличествоСуток <= 30
                            ТОГДА 2
                        ИНАЧЕ 3
                    КОНЕЦ
            КОНЕЦ
    КОНЕЦ КАК ОтсрочкаОплаты,
    ПродажиОбороты.ДокументПродажи КАК Док,
    ЕСТЬNULL(СУММА(ПродажиОбороты.СтоимостьОборот), 0) КАК Сумма
ПОМЕСТИТЬ ДанныеПродажи
ИЗ
    РегистрНакопления.Продажи.Обороты КАК ПродажиОбороты
ГДЕ
    ПродажиОбороты.ДоговорКонтрагента.Ссылка В(&ДоговорыКонтрагента)
    И ПродажиОбороты.ДокументПродажи.Дата <= &КонДатаПродаж
    И ПродажиОбороты.Контрагент.Ссылка = &Контрагент

СГРУППИРОВАТЬ ПО
    ПродажиОбороты.ДокументПродажи,
    НАЧАЛОПЕРИОДА(ПродажиОбороты.ДокументПродажи.Дата, ДЕНЬ),
    ВЫБОР
        КОГДА НЕ &ОтсрочкаПоСрокамГодностиТовара
            ТОГДА 0
        ИНАЧЕ ВЫБОР
                КОГДА ПродажиОбороты.Номенклатура.СрокГодностиТовара.КоличествоСуток < 10
                    ТОГДА 1
                ИНАЧЕ ВЫБОР
                        КОГДА ПродажиОбороты.Номенклатура.СрокГодностиТовара.КоличествоСуток >= 10
                                И ПродажиОбороты.Номенклатура.СрокГодностиТовара.КоличествоСуток <= 30
                            ТОГДА 2
                        ИНАЧЕ 3
                    КОНЕЦ
            КОНЕЦ
    КОНЕЦ
;

//////

"Медленный запрос"

ВЫБРАТЬ
    ВЫБОР
        КОГДА НЕ &ОтсрочкаПоСрокамГодностиТовара
            ТОГДА 0
        ИНАЧЕ ВЫБОР
                КОГДА ПродажиОбороты.Номенклатура.СрокГодностиТовара.КоличествоСуток < 10
                    ТОГДА 1
                ИНАЧЕ ВЫБОР
                        КОГДА ПродажиОбороты.Номенклатура.СрокГодностиТовара.КоличествоСуток >= 10
                                И ПродажиОбороты.Номенклатура.СрокГодностиТовара.КоличествоСуток <= 30
                            ТОГДА 2
                        ИНАЧЕ 3
                    КОНЕЦ
            КОНЕЦ
    КОНЕЦ КАК ОтсрочкаОплаты,
    ПродажиОбороты.ДокументПродажи КАК Док,
    НАЧАЛОПЕРИОДА(ПродажиОбороты.ДокументПродажи.Дата, ДЕНЬ) КАК ДатаДок,
    ЕСТЬNULL(СУММА(ПродажиОбороты.СтоимостьОборот), 0) КАК Сумма
ПОМЕСТИТЬ ДанныеПродажи
ИЗ
    РегистрНакопления.Продажи.Обороты(
            ,
            ,
            ,
            ДоговорКонтрагента В (&ДоговорыКонтрагента)
                И ДокументПродажи.Дата <= &КонДатаПродаж
                И Контрагент = &Контрагент) КАК ПродажиОбороты

СГРУППИРОВАТЬ ПО
    ПродажиОбороты.ДокументПродажи,
    НАЧАЛОПЕРИОДА(ПродажиОбороты.ДокументПродажи.Дата, ДЕНЬ),
    ВЫБОР
        КОГДА НЕ &ОтсрочкаПоСрокамГодностиТовара
            ТОГДА 0
        ИНАЧЕ ВЫБОР
                КОГДА ПродажиОбороты.Номенклатура.СрокГодностиТовара.КоличествоСуток < 10
                    ТОГДА 1
                ИНАЧЕ ВЫБОР
                        КОГДА ПродажиОбороты.Номенклатура.СрокГодностиТовара.КоличествоСуток >= 10
                                И ПродажиОбороты.Номенклатура.СрокГодностиТовара.КоличествоСуток <= 30
                            ТОГДА 2
                        ИНАЧЕ 3
                    КОНЕЦ
            КОНЕЦ
    КОНЕЦ
1 RomanYS
 
01.07.16
21:28
может меришь не правильно? Время выполнения какое?
2 Lexey_
 
01.07.16
21:30
(0) минимум дату не туда пишешь: РегистрНакопления.Обороты(&НачалоПериода, &КонецПериода, , )
3 cons74
 
01.07.16
21:32
(1) быстрый 1,000 медленный 1,300
(2)какую еще дату?!
4 floody
 
01.07.16
21:35
Автор, что сказать-то хотел?
5 Armando
 
01.07.16
21:35
Покажи планы запросов
6 floody
 
01.07.16
21:36
Условия надо нормальные писать, которые попадают в индексы.
7 MishaD
 
01.07.16
21:36
Для виртуальных таблиц вроде как группировка не нужна.
8 floody
 
01.07.16
21:37
Вместо "В" иногда лучше внутреннее или левое соединение.
9 RomanYS
 
01.07.16
21:38
я бы ещё попробовал разделить условия: простые (договор и контрагент) в параметры, а ДокументПродажи.Дата в ГДЕ
10 RomanYS
 
01.07.16
21:39
(3) замерь (9)
11 cons74
 
01.07.16
21:49
(9),(10) видимо причину замедления мы нашли - теперь скорость одинаковая. Но я - то хотел ускорить исходный запрос.
12 RomanYS
 
01.07.16
21:54
(11) ну можно засунуть классификацию номенклатуры в отдельную ВТ, и вместо ПродажиОбороты.Номенклатура.СрокГодностиТовара.КоличествоСуток делать явное левое соединение
13 RomanYS
 
01.07.16
21:56
ещё проанализировать есть ли ситуации, где ДокументПродажи.Дата отличается от Период. Может можно упростить
14 mehfk
 
01.07.16
22:01
(0) 1. Анализируй текст(ы) запроса(ов) SQL, а не исходный(е).
2. Оба запроса - гогно.
15 cons74
 
01.07.16
22:07
(14)2 - так я ж пытаюсь их оптимизировать. Кто-то писал, а я - разгребаю...
16 cons74
 
01.07.16
22:09
(12) это уже лишнее:

Итог: с 1 сек на 0,013 :)))

По рекомендациям http://курсы-по-1с.рф/articles/как-в-1с-оптимизировать-запрос/
создал предварительную ВТ с объединением выборок ссылок из документов, а уже потом здесь "ДокументПродажи в (выбрать ВТ_Док.ссылка из ВТ_Док)".
17 Злопчинский
 
01.07.16
22:09
(14)  какие одинэсники такие и запросы
Бугага стораз хихи
18 mehfk
 
01.07.16
22:13
ну и КоличествоСуток - если дофига где используется, то напрашивается денормализация

Ссылочный тип - СрокГодностиТовара тоже улыбно :)
19 cons74
 
01.07.16
22:21
(16) поспешил
Неправильно составил вт. Не получается ускорения все-таки.
20 RomanYS
 
01.07.16
22:24
(19) убери "ВЫБОР...", сделай замер. Если результат устроит, думай, что с этой конструкцией делать
21 cons74
 
01.07.16
22:31
(20) ну да, быстрее. Блин, обидно - все усилия по ДокументПродажи.Дата впустую. Не в нем дело видимо, а в Номенклатура.СрокГодностиТовара.КоличествоСуток
22 cons74
 
01.07.16
22:32
(12) можно чуть поподробнее?
23 cons74
 
01.07.16
22:47
а то стало только хуже

ВЫБРАТЬ
    Номенклатура.Ссылка КАК НоменклатураСсылка,
    СрокиГодностиТовара.КоличествоСуток
ПОМЕСТИТЬ ВТ_СуткиГодности
ИЗ
    Справочник.Номенклатура КАК Номенклатура
        ЛЕВОЕ СОЕДИНЕНИЕ Справочник.СрокиГодностиТовара КАК СрокиГодностиТовара
        ПО Номенклатура.СрокГодностиТовара = СрокиГодностиТовара.Ссылка
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
    НАЧАЛОПЕРИОДА(ПродажиОбороты.ДокументПродажи.Дата, ДЕНЬ) КАК ДатаДок,
    ВЫБОР
        КОГДА НЕ &ОтсрочкаПоСрокамГодностиТовара
            ТОГДА 0
        ИНАЧЕ ВЫБОР
                КОГДА ВТ_СуткиГодности.КоличествоСуток < 10
                    ТОГДА 1
                ИНАЧЕ ВЫБОР
                        КОГДА ВТ_СуткиГодности.КоличествоСуток МЕЖДУ 10 И 30
                            ТОГДА 2
                        ИНАЧЕ 3
                    КОНЕЦ
            КОНЕЦ
    КОНЕЦ КАК ОтсрочкаОплаты,
    ПродажиОбороты.ДокументПродажи КАК Док,
    ЕСТЬNULL(СУММА(ПродажиОбороты.СтоимостьОборот), 0) КАК Сумма
ПОМЕСТИТЬ ДанныеПродажи
ИЗ
    РегистрНакопления.Продажи.Обороты КАК ПродажиОбороты
        ЛЕВОЕ СОЕДИНЕНИЕ ВТ_СуткиГодности КАК ВТ_СуткиГодности
        ПО ПродажиОбороты.Номенклатура = ВТ_СуткиГодности.НоменклатураСсылка
ГДЕ
    ПродажиОбороты.ДоговорКонтрагента.Ссылка В(&ДоговорыКонтрагента)
    И ПродажиОбороты.ДокументПродажи.Дата <= &КонДатаПродаж
    И ПродажиОбороты.Контрагент.Ссылка = &Контрагент

СГРУППИРОВАТЬ ПО
    ПродажиОбороты.ДокументПродажи,
    НАЧАЛОПЕРИОДА(ПродажиОбороты.ДокументПродажи.Дата, ДЕНЬ),
    ВЫБОР
        КОГДА НЕ &ОтсрочкаПоСрокамГодностиТовара
            ТОГДА 0
        ИНАЧЕ ВЫБОР
                КОГДА ВТ_СуткиГодности.КоличествоСуток < 10
                    ТОГДА 1
                ИНАЧЕ ВЫБОР
                        КОГДА ВТ_СуткиГодности.КоличествоСуток МЕЖДУ 10 И 30
                            ТОГДА 2
                        ИНАЧЕ 3
                    КОНЕЦ
            КОНЕЦ
    КОНЕЦ
24 floody
 
01.07.16
22:50
Предлагаю посмотреть план запроса и оттуда плясать.
25 Cyberhawk
 
01.07.16
22:54
Ты еще учитывай при замерах, что первый замер только разогревает кэш СУБД...
26 4St
 
02.07.16
11:40
(23) ПродажиОбороты.ДоговорКонтрагента.Ссылка В(&ДоговорыКонтрагента)
Меняй на
ПродажиОбороты.ДоговорКонтрагента В(&ДоговорыКонтрагента)
То же самое с контрагентом.
Но реальные тормоза почти наверняка вызывает
ПродажиОбороты.ДокументПродажи.Дата <= &КонДатаПродаж
Поле ДокументПродажи часом не составное? Сколько в нем типов данных?
В чем смысл фильтрации регистра оборотов по дате документа вместо использования интервала дат в параметрах виртуальной таблицы?
27 4St
 
02.07.16
11:45
(23) и ещё, первую ВТ хорошо бы проиндексировать по НоменклатураСсылка.
А также Выбрать Различные на всякий случай, а ещё лучше - сгруппировать по номенклатуре, а срокгодности взять max/min.
По второму запросу - надо решить, как в отчете должны отражаться возвраты от покупателей. Если их нет, например, то фильтр дат задавать обычными параметрами вт.
28 Cyberhawk
 
02.07.16
11:54
(26) "В чем смысл фильтрации регистра оборотов по дате документа вместо использования интервала дат в параметрах виртуальной таблицы?" // Такое имеет смысл только если документ делает движения не своей датой, в случае с "ПродажиОбороты" это может быть только какая-то допилка "сбоку" по какому-нибудь планированию. Но вряд ли это случай автора.
(27) "первую ВТ хорошо бы проиндексировать по НоменклатураСсылка" // Зачем, если выборка из нее далее выполнятется только один раз?
29 4St
 
02.07.16
12:14
(28) я об этом:
ИЗ
    РегистрНакопления.Продажи.Обороты КАК ПродажиОбороты
        ЛЕВОЕ СОЕДИНЕНИЕ ВТ_СуткиГодности КАК ВТ_СуткиГодности
        ПО ПродажиОбороты.Номенклатура = ВТ_СуткиГодности.НоменклатураСсылка

Соединять лучше по индексированному полю. А затраты на индексацию должны быть незначительны.
30 PR
 
02.07.16
12:47
Поразительно, ни одной фразы про отбор в ПВТ по полю через точку.
(0) ТС, убери из ПВТ отбор по Документ.Дата, сделай его в ГДЕ. Или сделай отбор не по Документ.Дата, а по Документ в списке, который до этого вычисли по отбору по дате.
31 4St
 
02.07.16
12:52
(30) Почему же, в (26) как раз об этом писал.
Есть подозрение, что надо копнуть саму постановку задачи. Возможно, все удастся свести к обычному фильтру по периоду в виртуальной таблице. Либо понять, что под данную задачу нужен отдельный регистр / отдельное поле "ДатаДокументаПродажи" в РН "Продажи".
32 PR
 
02.07.16
12:55
(31) А, ну да, просмотрел
Кстати, фильтр по дате документа вполне может иметь смысл, почему нет-то? Документ продажи <> Регистратор.
33 4St
 
02.07.16
13:03
(32) Разумеется. О том и речь, что надо понять, что должно произойти, когда ДокументПродажи<>Регистратор, и есть ли такое вообще. Например, в компании не используются возвраты\корректировки реализации. Или внезапно окажется, что движения по таким документам надо все-таки отражать именно в их периоде действия. Иногда заказчик, отвечая повторно на такие запросы, хлопает себя по лбу и говорит "а, ну да, все совсем не так!" ))
34 echo77
 
02.07.16
16:54
(0) Отбор с помощью параметров ВТ не всегда приводит к ускорению, особенно, если вы не попадаете в индекс
35 mikeA
 
02.07.16
18:41
(20) попробуй заменить

            ВЫБОР
                КОГДА ПродажиОбороты.Номенклатура.СрокГодностиТовара.КоличествоСуток < 10
                    ТОГДА 1
                ИНАЧЕ ВЫБОР
                        КОГДА ПродажиОбороты.Номенклатура.СрокГодностиТовара.КоличествоСуток >= 10
                                И ПродажиОбороты.Номенклатура.СрокГодностиТовара.КоличествоСуток <= 30
                            ТОГДА 2
                        ИНАЧЕ 3
                    КОНЕЦ
            КОНЕЦ

на

            ВЫРАЗИТЬ(-40/(ПродажиОбороты.Номенклатура.СрокГодностиТовара.КоличествоСуток + 10) + 3.500000001 КАК ЧИСЛО(10, 0))

ну так, чиста чтоб поржать))
36 cons74
 
26.07.16
15:40
короче убрал Контрагента, оставил Договор. Получилось быстрее (как понял, за счет отсутствия лишнего условия по индексу, а индекс-то не непрерывный по таким-то условиям).
37 ViSo76
 
26.07.16
16:44
Пробуй так куски вставив по месту и заменив на правильное наименование справочника "ПравильноеНаименованиеСправочника"

ВЫБРАТЬ
    НАЧАЛОПЕРИОДА(ПродажиОбороты.Период, ДЕНЬ) КАК ДатаДок,

    ВЫБОР
        КОГДА НЕ &ОтсрочкаПоСрокамГодностиТовара
            ТОГДА 0
        ИНАЧЕ ВЫБОР
                КОГДА спрСрокГодностиТовара.КоличествоСуток < 10
                    ТОГДА 1
                ИНАЧЕ ВЫБОР
                        КОГДА спрСрокГодностиТовара.КоличествоСуток >= 10
                                И спрСрокГодностиТовара.КоличествоСуток <= 30
                            ТОГДА 2
                        ИНАЧЕ 3
                    КОНЕЦ
            КОНЕЦ
    КОНЕЦ КАК ОтсрочкаОплаты,
...

ИЗ
    РегистрНакопления.Продажи.Обороты(
            ,
            ,
            &КонДатаПродаж,
            Контрагент = &Контрагент И ДоговорКонтрагента В ( &ДоговорыКонтрагента )
    ) КАК ПродажиОбороты

    ЛЕВОЕ СОЕДИНЕНИЕ Справочник.Номенклатура КАК спрНоменклатура
    ПО спрНоменклатура.Ссылка = ПродажиОбороты.Номенклатура

    ЛЕВОЕ СОЕДИНЕНИЕ Справочник."ПравильноеНаименованиеСправочника" КАК спрСрокГодностиТовара
    ПО спрСрокГодностиТовара.Ссылка = спрНоменклатура.СрокГодностиТовара
38 ViSo76
 
26.07.16
16:46
Ошибся малость

РегистрНакопления.Продажи.Обороты(
            ,
            &КонДатаПродаж,
            ,
39 Dmitrii
 
гуру
26.07.16
17:22
(32) (33) Даже если ДокументПродажи <> Регистратор, это не мешает нам поставить условие виртуальной таблицы на КонецПериода <= &КонДатаПродаж
Т.к. даже в случаях возвратов или последующих каких-то движений молавероятна ситуация, когда Период в регистре будет < ДокументПродажи.Дата
Не может быть возврат раньше документа продажи.

Кроме того, я быпоставил условие на параметр виртуальной таблицы &НачалоПериода. Учитывая сроки годности, исчисляемые сутками, можно например влепить пол года от &КонДатаПродаж.

И вообще таблицу Обороты имеет смысл использовать, когда речь идёт о выборке по ограниченному периоду. Если ограничить период никак нельзя, то физическая таблица первичных движений частенько работает быстрее. Что и наблюдается у автора в (0).
40 kiruha
 
26.07.16
17:37
(0)
За такое
И ДокументПродажи.Дата <= &КонДатаПродаж

сразу увольнять
41 Fragster
 
гуру
26.07.16
17:40
если скорость обработки данных зависит от срока эксплуатации системы - это значит, что данные организованы неправильно. в данном случае чем больше времени проходит - тем дольше будет выполняться запрос. это неправильно, следует подумать об изменении структуры.
42 ViSo76
 
26.07.16
18:02
(39) Где у автора в запросе таблица первичных движений?
43 Necessitudo
 
26.07.16
18:07
(42) Таблица "Обороты" строится на объединении таблицы итогов и таблицы движений.
44 ViSo76
 
26.07.16
18:32
(43) 1. Ты путаешь ОстаткиИОбороты
2. РегистрНакопления.Продажи.Обороты не одно и тоже что и РегистрНакопления.Продажи
45 Sammo
 
26.07.16
20:27
Обращение через 2 точки - это неявное соединения с таблицами всех типов, которые входят в документы продажи.
В первом случае ты выбираешь обороты и потом к этому накладываешь соединения.
Во втором ты накладываешь соединения и от всего этого разнообразия выцарапываешь обороты.
Две точки зло.
Ну номенклатуру предварительно подготовить
Проблема с подобными запросами, что они на небольших объемах данных могут работать быстро. А когда объем данных растет, то план запроса может строиться по-иному. Причем невсегда предсказуемо.
Поэтому переходить на ВТ - это позволит как-то прогнозировать план запроса вне зависимости от данных
P.S. видел как отказ от вложенных запросов, отказ от двух точек и переход на ВТ существенно ускорял запросы, которые на больших объемах данных внезапно стали тупить
46 echo77
 
26.07.16
20:41
(40) Вы не учитываете особенность данного регистра - запиши пишут не только документы продажи(РТУ, Акт об оказании услуг) но и Корректировка реализации - которая не сильно кого интересует, т.к. продажа могла состояться в другом периоде.
Эта особенность и приводит к такому условию
47 wertyu
 
26.07.16
20:54
(0) второе поле запроса составлено криво, для читаемости надо так: выбор когда параметр тогда {тут выбор по количеству 1,2,3} иначе 0 конец
48 wertyu
 
26.07.16
21:02
+(47) {выбор по количеству}:
выбор когда 10 тогда 1
когда 10 и 30 тогда 2
иначе 3 конец
49 wertyu
 
26.07.16
21:05
а в последнем поле естьnull и сумма поменять местами
50 ViSo76
 
26.07.16
22:43
(46) У тебя движения зафиксированы в регистре с датой в поле "период" даже если у документа отличная дата то нужно использовать дату фиксации движений, а не дату документа, которая обычно = дате движения. По этому все неявные соединения со всеми возможными документами регистратора это плохой тон. Даже если и хочется использовать дату документов, то можно из физической таблицы считать данные <= &КонДатаПродаж вытащить ( РАЗЛИЧНЫЕ ) регистраторы в ВТ и там уже сделать неявное соединение документами с фильтрацией по дате. Так будет уменьшено количество соединений существенно, особенно если товара много в документах.
Компьютер — устройство, разработанное для ускорения и автоматизации человеческих ошибок.