|
Помогите оптимизировать запрос | ☑ | ||
---|---|---|---|---|
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) И что?... Зачем дважды - понятно. А срез то зачем нужен? Почему нельзя ВЫБРАТЬ Номенклатура, МАКСИМУМ(Период) ГДЕ ВидДоговора = &ВидДоговора и Период <=&Дата с внутренним соединением с ТаблицаТоваров ПО Номенклатура?
Срезы здесь явно избыточны, если мы всё равно делаем группировку. |
Форум | Правила | Описание | Объявления | Секции | Поиск | Книга знаний | Вики-миста |