Имя: Пароль:
1C
 
Помогите оптимизировать запрос
,
0 SherifSP
 
13.03.17
15:23
Здравствуйте мистяны, столкнулся с проблемой долгого выполнения запроса который представлен ниже, когда количество позиций в табличной части документа меньше или равно 45, тогда запрос выполняется 3 секунды, когда количество товара превышает показатель 45 позиций, запрос выполняется 21 минуту, подскажите, что можно сделать чтобы ускорить выполнение, буду очень благодарен.


ВЫБРАТЬ
    Товары.Номенклатура КАК Номенклатура,
    Товары.Цена КАК ЦенаПродажи
ПОМЕСТИТЬ ТаблицаТоваров
ИЗ
    &ТаблицаТоваров КАК Товары

ИНДЕКСИРОВАТЬ ПО
    Номенклатура
;

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

СГРУППИРОВАТЬ ПО
    ПериодыЦен.Номенклатура

ИНДЕКСИРОВАТЬ ПО
    Номенклатура
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
    Товары.Номенклатура КАК Номенклатура,
    Товары.ЦенаПродажи КАК ЦенаПродажи,
    ЦеныЗакупки.ЦенаЗакупки КАК ЦенаЗакупки,
    ВЫБОР
        КОГДА ЕСТЬNULL(ЦеныЗакупки.ЦенаЗакупки, 0) = 0
            ТОГДА 999999999
        ИНАЧЕ (Товары.ЦенаПродажи - ЦеныЗакупки.ЦенаЗакупки) / ЦеныЗакупки.ЦенаЗакупки * 100
    КОНЕЦ КАК Наценка
ИЗ
    ТаблицаТоваров КАК Товары
        ЛЕВОЕ СОЕДИНЕНИЕ ЦеныЗакупки КАК ЦеныЗакупки
        ПО Товары.Номенклатура = ЦеныЗакупки.Номенклатура
ГДЕ
    ЕСТЬNULL(ЦеныЗакупки.ЦенаЗакупки, 0) <> 0
1 SherifSP
 
13.03.17
15:25
+ (0) Реиндексация таблицы в скуле была сделана
2 SherifSP
 
13.03.17
15:25
Подозреваю, что криво написан запрос
3 ERWINS
 
13.03.17
15:28
ПоследниеЦеныЗакупок.СрезПоследних(&Дата, ВидДоговора = &ВидДоговора)

если можешь внеси внутрь номенклатуру.
4 ERWINS
 
13.03.17
15:28
СГРУППИРОВАТЬ ПО
        ТаблицаТоваров.Номенклатура) КАК ПериодыЦен
        ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ПоследниеЦеныЗакупок.СрезПоследних(&Дата, ВидДоговора = &ВидДоговора) КАК ПоследниеЦеныЗакупокСрезПоследних
        ПО ПериодыЦен.Номенклатура = ПоследниеЦеныЗакупокСрезПоследних.Номенклатура
            И ПериодыЦен.Период = ПоследниеЦеныЗакупокСрезПоследних.Период

это плохо
попробуй вынести во внутренюю таблицу.
5 SherifSP
 
13.03.17
15:29
(3) Сейчас попробую
6 mistеr
 
13.03.17
15:33
1. Вместо соединения СрезПоследних() с ТаблицаТоваров

СрезПоследних(&Дата, ВидДоговора = &ВидДоговора И Номенклатура В (ВЫБРАТЬ Номенклатура ИЗ ТаблицаТоваров))

2. Зачем два раза получаешь одинаковый СрезПоследних()?
7 SherifSP
 
13.03.17
15:38
(6) Не мной написан запрос)
8 Широкий
 
13.03.17
15:46
(0) ДОбавить отбор в СрезПоследних по списку номенклатуры
9 mistеr
 
13.03.17
15:49
(7) Это тапа оправдание, чтобы не вникать в его суть?
10 mistеr
 
13.03.17
15:50
(9) *типа*
11 RomanYS
 
13.03.17
15:50
(0) Структуру (измерения) регистра ПоследниеЦеныЗакупок озвучь.
12 SherifSP
 
13.03.17
15:54
(8) Добавил, все равно долго http://s009.radikal.ru/i309/1703/b0/d8193be9d151.jpg
13 SherifSP
 
13.03.17
15:56
+ (12) это я завершил сеанс, он бы еще дольше выполнялся
14 Широкий
 
13.03.17
15:57
полностью запрос напиши
15 SherifSP
 
13.03.17
15:58
(11) Структура регистра http://s014.radikal.ru/i327/1703/2d/29044d0a9d40.jpg
16 mexanik_96
 
13.03.17
16:00
может с плана лучше начать? а так индексы по регистру какие? зачем вложенный?
17 Широкий
 
13.03.17
16:03
(15) запрос напиши сюда
18 RomanYS
 
13.03.17
16:04
(15) Оптимально для данных целей сделать ещё один регистр с одним измерением и тупо брать по нему срез.

Можно ещё попробовать коррелированный запрос вместо твоего соединения
19 ERWINS
 
13.03.17
16:04
ВЫБРАТЬ
    ПериодыЦен.Номенклатура КАК Номенклатура,
    ВЫБОР
        КОГДА НЕ &ЦенаСНДС
            ТОГДА МАКСИМУМ(ЕСТЬNULL(ПоследниеЦеныЗакупокСрезПоследних.ЦенаБезНДС, 0))
        ИНАЧЕ МАКСИМУМ(ЕСТЬNULL(ПоследниеЦеныЗакупокСрезПоследних.ЦенаСНДС, 0))
    КОНЕЦ КАК ЦенаЗакупки
ПОМЕСТИТЬ ЦеныЗакупки
ИЗ
        ТаблицаТоваров КАК ТаблицаТоваров
            ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ПоследниеЦеныЗакупок.СрезПоследних(&Дата, ВидДоговора = &ВидДоговора и номенклатура В (выбрать различные Т.Номенклатура из ТаблицаТоваров )) КАК ПоследниеЦеныЗакупокСрезПоследних
            ПО ТаблицаТоваров.Номенклатура = ПоследниеЦеныЗакупокСрезПоследних.Номенклатура
    

ИНДЕКСИРОВАТЬ ПО
    Номенклатура
20 ERWINS
 
13.03.17
16:05
ВЫБРАТЬ
    ПериодыЦен.Номенклатура КАК Номенклатура,
    ВЫБОР
        КОГДА НЕ &ЦенаСНДС
            ТОГДА ЕСТЬNULL(ПоследниеЦеныЗакупокСрезПоследних.ЦенаБезНДС, 0)
        ИНАЧЕ ЕСТЬNULL(ПоследниеЦеныЗакупокСрезПоследних.ЦенаСНДС, 0)
    КОНЕЦ КАК ЦенаЗакупки
ПОМЕСТИТЬ ЦеныЗакупки
ИЗ
        ТаблицаТоваров КАК ТаблицаТоваров
            ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ПоследниеЦеныЗакупок.СрезПоследних(&Дата, ВидДоговора = &ВидДоговора и номенклатура В (выбрать различные Т.Номенклатура из ТаблицаТоваров )) КАК ПоследниеЦеныЗакупокСрезПоследних
            ПО ТаблицаТоваров.Номенклатура = ПоследниеЦеныЗакупокСрезПоследних.Номенклатура
    

ИНДЕКСИРОВАТЬ ПО
    Номенклатура
21 Широкий
 
13.03.17
16:05
(19) Индексировать то нафига? 45 позиций
22 SherifSP
 
13.03.17
16:05
(16) Индексов нет, по измерениям "Контрагент" и "Номенклатура" установлен признак "Ведущее"
23 H A D G E H O G s
 
13.03.17
16:05
Оптимально вообще отказаться от периодических регистров.
24 Тыгдымчик
 
13.03.17
16:06
А зачем в ПВТ делать подзапрос, если итак идет соединение?
25 Широкий
 
13.03.17
16:07
(22) Ты итоговый запрос будешь показывать или нет?
26 SherifSP
 
13.03.17
16:07
Вообще запрос возвращает процент наценки по товару чтобы проконтролировать и не дать пробить товар ниже себестоимости
27 mexanik_96
 
13.03.17
16:07
(22) это плохо...
28 SherifSP
 
13.03.17
16:07
(25) Сейчас скину
29 Wirtuozzz
 
13.03.17
16:08
(23) В запросе? или в целом?
30 Тыгдымчик
 
13.03.17
16:09
И зачем делать соединение с таблицей, из которой не выбирается ни одно поле?
31 RomanYS
 
13.03.17
16:10
(20) у него в срезе может быть 100500 записей по одной номенклатуре, а ему надо последнюю. Даже соединение по периоду не гарантирует одну запись, в твоем случае он получит все 100500
32 SherifSP
 
13.03.17
16:11
(25) ВЫБРАТЬ Товары.Номенклатура КАК Номенклатура,
    Товары.Цена КАК ЦенаПродажи
ПОМЕСТИТЬ ТаблицаТоваров
ИЗ &ТаблицаТоваров КАК Товары


ИНДЕКСИРОВАТЬ ПО
    Номенклатура
;

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

СГРУППИРОВАТЬ ПО
    ПериодыЦен.Номенклатура

ИНДЕКСИРОВАТЬ ПО
    Номенклатура
;

ВЫБРАТЬ Товары.Номенклатура КАК Номенклатура,
    Товары.ЦенаПродажи КАК ЦенаПродажи,
    ЦеныЗакупки.ЦенаЗакупки КАК ЦенаЗакупки,
    ВЫБОР КОГДА ЕстьNull(ЦеныЗакупки.ЦенаЗакупки,0) = 0 ТОГДА 999999999
            ИНАЧЕ (Товары.ЦенаПродажи-ЦеныЗакупки.ЦенаЗакупки)/ЦеныЗакупки.ЦенаЗакупки*100
    КОНЕЦ КАК Наценка
ИЗ ТаблицаТоваров КАК Товары
    ЛЕВОЕ СОЕДИНЕНИЕ ЦеныЗакупки КАК ЦеныЗакупки
        ПО Товары.Номенклатура = ЦеныЗакупки.Номенклатура
ГДЕ ЕстьNull(ЦеныЗакупки.ЦенаЗакупки,0)<>0
33 H A D G E H O G s
 
13.03.17
16:12
(29) В целом
34 mexanik_96
 
13.03.17
16:13
"посторитель запроса" субд работает по индексам если нет сканиться вся таблицы и записи выбираются в цикле... смысл текст запроса править если "посторитель запроса" сделает все подругому? посмотри план еще раз тебе рекомендую...
35 H A D G E H O G s
 
13.03.17
16:13
(30) Фильтр :-)
36 RomanYS
 
13.03.17
16:14
(26) вообще говоря, последняя цена закупки и себестоимость - сильно разные вещи
37 Wirtuozzz
 
13.03.17
16:16
(33) А как без них? Запросом вытаскивать запись с максимальной датой и считать ее срезом последних? Так быстрее получается работает чем просто взять срез последних?
38 H A D G E H O G s
 
13.03.17
16:18
39 H A D G E H O G s
 
13.03.17
16:20
(37) Для малозаполненных регистров можно пойти по другому пути - копировать все записи на новую дату при каждом изменении. И в кэше держать все даты изменений, подбирая ближайшую при выполнении запроса.
40 H A D G E H O G s
 
13.03.17
16:20
Но СрезПоследних - это зло.
41 rabbidX
 
13.03.17
16:24
(0) Индексировать временную таблицу до 1000 строк смысла нет.
Соединение с виртуальной таблицой может работать медленно, попробуйте заменить на виртуальную таблицу на временную.
Соединение с вложенным запросом может работать меделенно. Замените вложенный запрос на временную таблицу.
Срез последних по измерению выдаст по одной записи для каждого значения измерения, группировать там нечего, этот запрос можно выкинуть.

ВЫБОР
        КОГДА ЕСТЬNULL(ЦеныЗакупки.ЦенаЗакупки, 0) = 0
            ТОГДА 999999999
        ИНАЧЕ (Товары.ЦенаПродажи - ЦеныЗакупки.ЦенаЗакупки) / ЦеныЗакупки.ЦенаЗакупки * 100
    КОНЕЦ КАК Наценка
Здесь лишнее условие, т.к. дальше накладывается условие ЕСТЬNULL(ЦеныЗакупки.ЦенаЗакупки, 0) <> 0, удалите лишнее.

(6)"1. Вместо соединения СрезПоследних() с ТаблицаТоваров

СрезПоследних(&Дата, ВидДоговора = &ВидДоговора И Номенклатура В (ВЫБРАТЬ Номенклатура ИЗ ТаблицаТоваров))"
Не факт. Операторы В, В Иерархии, ИЛИ в параметрах виртуальной таблицы потенциально медленные. Соединение может отрабатывать быстрее. Нужно подбирать экспериментально, все зависит от размеров таблиц.
42 Wirtuozzz
 
13.03.17
16:26
(38) СПС, интересно, видел такое, не в ценах. К стати с помощью такой структуры данных можно влет определять длительность, т.к. в одной записе РС есть все нужные данные.
43 H A D G E H O G s
 
13.03.17
16:28
(42) Длительность чего?
44 H A D G E H O G s
 
13.03.17
16:29
Немного не понял.
45 Wirtuozzz
 
13.03.17
16:30
(43) Длительность установки цены. Скажу сразу, в контексте данной задачи с ценами - смысла в этом нет.

Но подобная структура РС полезна для РС статусов документов, там иногда хотят видеть длительность обработки статусов.
46 H A D G E H O G s
 
13.03.17
16:32
(45) Ясно.
47 Elatiell
 
13.03.17
16:43
(0) ответ в (41)

кроме этого
ВидДоговора = &ВидДоговора И Номенклатура В (ВЫБРАТЬ Номенклатура ИЗ ТаблицаТоваров)

Лучше добавить &ВидДоговора в ТаблицаТоваров, и сделать множественный выбор (ВидДоговора, Номенклатура) В (ВЫБРАТЬ Номенклатура,ВидДоговора ИЗ ТаблицаТоваров)

Это самое первое от чего нужно избавится.
Если после применения рекомендаций из (41) опять будет медленно выполнятся, тогда нужно рыть дальше.

Я бы еще добавил следующее, раз индексов в регистре нет, кроме стандартных, то попробуйте проиндексировать ВидДоговора, и поставить его в регистре под Номенклатурой.
48 Elatiell
 
13.03.17
16:47
(47) Правда с перемещением под номенклатуру нужно быть аккуратным и быть уверенyым, что другие запросы у Вас не загнутся. :P
49 H A D G E H O G s
 
13.03.17
17:05
(48) (47) Вообще надо быть крайне увереным (в себе), что индексация вместе с перемещением к чему-то приведет.
50 Dmitrii
 
гуру
13.03.17
17:21
Как у вас тут интересно...
А хоть кто-нибудь может объяснить для чего тут СрезПоследних да еще и дважды? И почему соединения левые для получения ЦеныЗакупки, а не внутренние?
У меня доступ к ссылкам в (15) нет, структуры регистра не знаю.
ИМХО, запроса достаточно одного и к первичной таблице регистра.
51 RomanYS
 
13.03.17
17:30
(50) в (15) кроме номенклатуры ещё 4 измерения
52 Elatiell
 
13.03.17
17:54
(49) Приведет.
53 xxTANATORxx
 
13.03.17
17:58
(0)если не хочешь копаться с планом запроса, тогда кидай всё во времянки, явно выражай типы
54 Dmitrii
 
гуру
13.03.17
18:04
(51) И что?... Зачем дважды - понятно. А срез то зачем нужен? Почему нельзя ВЫБРАТЬ Номенклатура, МАКСИМУМ(Период) ГДЕ ВидДоговора = &ВидДоговора и Период <=&Дата  с внутренним соединением с ТаблицаТоваров ПО Номенклатура?
Срезы здесь явно избыточны, если мы всё равно делаем группировку.
Компьютеры — прекрасное средство для решения проблем, которых до их появления не было.