|
Оптимизация быстродействия запроса | ☑ | ||
---|---|---|---|---|
0
bluekrab
22.10.15
✎
12:41
|
Добрый день. Помогите оптимизировать запрос. Не могу понять, что влияет на его быстродействие.
ВЫБРАТЬ РеализацияТоваровУслугТовары.Номенклатура КАК Товар, РеализацияТоваровУслугТовары.Цена КАК Цена, РеализацияТоваровУслугТовары.Количество, РеализацияТоваровУслугТовары.ЕдиницаИзмерения КАК ЕдиницаХранения, РеализацияТоваровУслугТовары.Сумма, РеализацияТоваровУслугТовары.Ссылка.Ссылка, РеализацияТоваровУслугТовары.СуммаНДС, РеализацияТоваровУслугТовары.СтавкаНДС.Ссылка ПОМЕСТИТЬ ВР ИЗ Документ.РеализацияТоваровУслуг.Товары КАК РеализацияТоваровУслугТовары ГДЕ РеализацияТоваровУслугТовары.Ссылка.Ссылка В(&Регистратор) ; //////////////////////////////////////////////////////////////////////////////// ВЫБРАТЬ ВР.Товар, ВР.Количество КАК Количество, ВР.ЕдиницаХранения, ВЫРАЗИТЬ(ХозрасчетныйДвиженияССубконто.Сумма / ХозрасчетныйДвиженияССубконто.КоличествоКт КАК ЧИСЛО(10, 2)) КАК ЦенаЗакупки, ХозрасчетныйДвиженияССубконто.Сумма КАК СуммаЗакупки, ВР.Сумма КАК Сумма, ВР.СуммаНДС, ВР.Цена КАК Цена ИЗ ВР КАК ВР ЛЕВОЕ СОЕДИНЕНИЕ РегистрБухгалтерии.Хозрасчетный.ДвиженияССубконто(, , Счет = &Счёт, , ) КАК ХозрасчетныйДвиженияССубконто ПО (ХозрасчетныйДвиженияССубконто.СубконтоКт1 = ВР.Товар) И (ХозрасчетныйДвиженияССубконто.Регистратор = ВР.Ссылка) |
|||
1
sash-ml
22.10.15
✎
12:46
|
ДвиженияССубконто(, , Счет = &Счёт и сюда условие на регистратор не?, , )
|
|||
2
H A D G E H O G s
22.10.15
✎
12:47
|
РеализацияТоваровУслугТовары.Ссылка.Ссылка В(&Регистратор)
на РеализацияТоваровУслугТовары.Ссылка В(&Регистратор) |
|||
3
Рэйв
22.10.15
✎
12:49
|
(0)Проиндексируй ВТ по Товар и Ссылка
|
|||
4
asady
22.10.15
✎
12:50
|
(0) ограничь снизу и сверху период
у тебя же тупой скан по всей таблице движений с субконто |
|||
5
mistеr
22.10.15
✎
12:51
|
(3) ВТ вообще лишняя.
|
|||
6
GANR
22.10.15
✎
12:53
|
(0) .Ссылка.Ссылка - сразу в глаза бросилось, это точно не окажет положительного влияния на быстродействие
|
|||
7
asady
22.10.15
✎
12:55
|
||||
8
GANR
22.10.15
✎
12:55
|
+(6) а нельзя ли ДвиженияССубконто на ОборотыДтКт заменить?
|
|||
9
User_Agronom
22.10.15
✎
12:55
|
(1) (5) Да.
|
|||
10
GANR
22.10.15
✎
12:56
|
Ооооой... Да тут еще перед соединением с регистром последний надо по регистратору отфильтровать
|
|||
11
GANR
22.10.15
✎
12:57
|
(1) - точно (5) - не факт
|
|||
12
GANR
22.10.15
✎
12:58
|
(3) если записей в таблице менее 20 - индекс только навредит
|
|||
13
GANR
22.10.15
✎
13:00
|
и еще: Вы уверены, что в табличной части не будет дублей?
|
|||
14
GANR
22.10.15
✎
13:02
|
(0) >Не могу понять, что влияет на его быстродействие.
Да? А я не могу понять, почему этот запрос должен работать быстро. |
|||
15
ViSo76
22.10.15
✎
13:11
|
Вместо:
ЛЕВОЕ СОЕДИНЕНИЕ РегистрБухгалтерии.Хозрасчетный.ДвиженияССубконто(, , Счет = &Счёт, , ) КАК ХозрасчетныйДвиженияССубконто Поставь: ЛЕВОЕ СОЕДИНЕНИЕ РегистрБухгалтерии.Хозрасчетный.ДвиженияССубконто(, , Регистратор В ( &Регистратор ) И Счет = &Счёт, , ) КАК ХозрасчетныйДвиженияССубконто |
|||
16
ViSo76
22.10.15
✎
13:35
|
(6) Да там тупо будет соединение левое. Если головной таблицей станет РеализацияТоваровУслуг то провала производительности не будет, хотя я предпочитаю писать без точек всегда. Использую точку если без неё много городить придётся и точно знаю что на быстродействие эта точка не скажется.
(3) Индексация вообще никак не спасёт (5) В данном случае ВТ лишняя на 100%. Увлечение без повода ВТ перегружает временную базу данных что сказывается на общей производительности. |
|||
17
GANR
22.10.15
✎
13:39
|
(16) >В данном случае ВТ лишняя на 100%.
А уверены, что в выборе НЕ нужны позиции, по которым нет проводок? |
|||
18
GANR
22.10.15
✎
13:39
|
+(17) ^в выборе
в выборКе |
|||
19
ViSo76
22.10.15
✎
13:48
|
(17) А тебя что кто-то заставляет присоединять к проводкам документ? В место той же ВТ можно сделать выборку в документе и присоединить ЛЕВЫМ соединением проводки
|
|||
20
GANR
22.10.15
✎
14:13
|
(19) Это верно, но вот если в табличной части может быть 2 строки с одним товаром (нет технического ограничения на дубли), то ее надо сворачивать, а это лучше сделать в рамках временной таблицы. Я хочу сказать, что запрос не только медленный, но и с точки зрения правильности возвращаемых данных заведомо неверный.
|
|||
21
ViSo76
22.10.15
✎
14:30
|
(20) Тебе религия запрещает свернуть и потом присоединить движения без временной таблицы?
|
|||
22
Лефмихалыч
22.10.15
✎
14:33
|
Условия на виды субконто надо наложить еще (первый параметр)
|
|||
23
GANR
22.10.15
✎
14:50
|
(21) Не религия - оптимизатор MS SQL, который может решить, что рациональней выполнять запрос в цикле.
|
|||
24
GANR
22.10.15
✎
14:52
|
+(23) такое бывает при использовании вложенных запросов
|
|||
25
ViSo76
22.10.15
✎
14:55
|
(23) У тебя "вложенный" будет головой таблицей по этому не понимаю о каких циклах ты вещаешь
|
|||
26
GANR
22.10.15
✎
15:00
|
(25) А просто возьми и попробуй посоединять большие таблицы с вложенными запросами разными способами - лично я убедился, что это ужасно влияет на быстродействие и уже не раз переделывал такие "разработки". 1С в своих стандартах не рекомендует соединения с вложенными запросами. Свертку с их помощью - ради Бога, но соединять - никогда.
|
|||
27
ViSo76
22.10.15
✎
15:05
|
(26) В данном случае НЕТ соединений с вложенным. В начале отбирается вложенный и потом соединяется с виртуальной с нормальным отбором ( не со всеми движениями начиная от рождения Иисуса ). Зачем набрасывать на вентилятор того чего НЕТ в данном запросе?
|
|||
28
GANR
22.10.15
✎
15:11
|
(27) > НЕТ соединений с вложенным
Это заблуждение - если мы используем вложенный запрос, то оптимизатор может как угодно построить план запроса. |
|||
29
bluekrab
22.10.15
✎
15:11
|
(15) Спасибо большое. Ваш совет помог
|
|||
30
GANR
22.10.15
✎
15:12
|
Это только визуально нам кажется, что сначала всё отберется из ВЗ
|
|||
31
ViSo76
22.10.15
✎
15:16
|
(30) Понятно что в начале будет отборы, а в конце самом левое соединение. Ты же не думаешь что виртуальная таблица уже готовая? По этому всё что ты набрасывал ранее это просто дуть на воду. Поверь в данном случае вода холодная. Какие ты ещё там циклы увидел...
|
|||
32
ViSo76
22.10.15
✎
15:17
|
(29) Тема фотографии не раскрыта
|
|||
33
MadJhey
22.10.15
✎
15:22
|
(27) любая виртуальная таблица - это вложенный запрос в SQL
|
|||
34
ViSo76
22.10.15
✎
15:26
|
(33) Опиши что будет делать MS SQL пошагово для данного запроса.
PS: Я тоже знаю КАРАТЕ, ДЗЮДО и много ещё страшных слов. |
|||
35
GANR
22.10.15
✎
15:30
|
(34) Оптимизатор может для одного и того же запроса несколько различных планов выполнения построить на свое усмотрение. А если временную таблицу задействовать - вот тут можно четко знать что произойдет.
|
|||
36
ViSo76
22.10.15
✎
15:32
|
(35) С данным утверждением я не спорю но как это относится к данному запросу? Все что будет выбрано - будет выбрано по индексам остальное дело процессора. Вы пытаетесь блох поймать. Если просто попугать на будущее, то так и пишите в начале, что вы ударились в философию.
|
|||
37
sash-ml
22.10.15
✎
15:38
|
(33) да ладно tempDB не существует?
|
|||
38
MadJhey
22.10.15
✎
17:11
|
(32) Ок. Рассмотрим вторую часть запроса, в первой временной таблице все понятно
ВЫБРАТЬ ВР.Товар, ВР.Количество КАК Количество, ВР.ЕдиницаХранения, ВЫРАЗИТЬ(ХозрасчетныйДвиженияССубконто.Сумма / ХозрасчетныйДвиженияССубконто.КоличествоКт КАК ЧИСЛО(10, 2)) КАК ЦенаЗакупки, ХозрасчетныйДвиженияССубконто.Сумма КАК СуммаЗакупки, ВР.Сумма КАК Сумма, ВР.СуммаНДС, ВР.Цена КАК Цена ИЗ ВР КАК ВР ЛЕВОЕ СОЕДИНЕНИЕ РегистрБухгалтерии.Хозрасчетный.ДвиженияССубконто(, , Счет = &Счёт, , ) КАК ХозрасчетныйДвиженияССубконто ПО (ХозрасчетныйДвиженияССубконто.СубконтоКт1 = ВР.Товар) И (ХозрасчетныйДвиженияССубконто.Регистратор = ВР.Ссылка) на SQL это будет exec sp_executesql N'SELECT T1._Q_000_F_000RRef, T1._Q_000_F_002, T1._Q_000_F_003RRef, CAST((CAST(T2.Fld466_ AS NUMERIC(21, 8)) / T2.Fld468Ct_) AS NUMERIC(10, 2)), T2.Fld466_, T1._Q_000_F_004, T1._Q_000_F_006, T1._Q_000_F_001 FROM #tt1 T1 WITH(NOLOCK) LEFT OUTER JOIN (SELECT T3._RecorderTRef AS RecorderTRef, T3._RecorderRRef AS RecorderRRef, T3._Fld466 AS Fld466_, T3._Fld468Ct AS Fld468Ct_, T3._ValueCt1_TYPE AS ValueCt1_TYPE, T3._ValueCt1_RTRef AS ValueCt1_RTRef, T3._ValueCt1_RRRef AS ValueCt1_RRRef FROM #tt2 T3 WITH(NOLOCK)) T2 ON ((T2.ValueCt1_TYPE = CASE WHEN T1._Q_000_F_000RRef IS NOT NULL THEN 0x08 END AND T2.ValueCt1_RTRef = CASE WHEN T1._Q_000_F_000RRef IS NOT NULL THEN P1 END AND T2.ValueCt1_RRRef = T1._Q_000_F_000RRef) AND (T2.RecorderTRef = CASE WHEN T1._Q_000_F_005RRef IS NOT NULL THEN @P2 END AND T2.RecorderRRef = T1._Q_000_F_005RRef))',N'P1 varbinary(4),@P2 varbinary(4)',0x00000036,0x000000C1 |
|||
39
MadJhey
22.10.15
✎
17:13
|
где #tt1 - это ВР,
а #tt2 - это временная таблица с результатом расчета движения по субконто. |
|||
40
MadJhey
22.10.15
✎
17:14
|
тут еще куча промежуточных временных таблиц. смухлюю приведу расчет для упрощенного варианта.
Выбрать Первые 11 ХозрасчетныйДвиженияССубконто.Сумма Из РегистрБухгалтерии.Хозрасчетный.ДвиженияССубконто(, , Счет = &Счёт, , ) КАК ХозрасчетныйДвиженияССубконто exec sp_executesql N'SELECT TOP 11 T1.Fld466_ FROM (SELECT T5._Fld466 AS Fld466_ FROM (SELECT DISTINCT T3._RecorderTRef AS RecorderTRef, T3._RecorderRRef AS RecorderRRef, T3._LineNo AS LineNo_ FROM _AccRg462 T3 WITH(NOLOCK) WHERE ((T3._AccountDtRRef = P1)) UNION SELECT T4._RecorderTRef AS RecorderTRef, T4._RecorderRRef AS RecorderRRef, T4._LineNo AS LineNo_ FROM _AccRg462 T4 WITH(NOLOCK) WHERE ((T4._AccountCtRRef = @P2))) T2 INNER JOIN _AccRg462 T5 WITH(NOLOCK) ON T5._RecorderTRef = T2.RecorderTRef AND T5._RecorderRRef = T2.RecorderRRef AND T5._LineNo = T2.LineNo_) T1',N'P1 varbinary(16),@P2 varbinary(16)',0x9AE320D5E1503F5A4C3421B79A621088,0x9AE320D5E1503F5A4C3421B79A621088 |
|||
41
MadJhey
22.10.15
✎
17:15
|
если это не вложенные таблицы, то как выглядят вложенные?
|
|||
42
MadJhey
22.10.15
✎
17:17
|
(41) вложенный запрос ... пардон
|
|||
43
singlych
22.10.15
✎
17:19
|
Ну все, впредь никаких левых соединений с виртуальными таблицами.
|
|||
44
H A D G E H O G s
22.10.15
✎
17:21
|
(43) Очень зря.
|
|||
45
H A D G E H O G s
22.10.15
✎
17:21
|
"любая виртуальная таблица - это вложенный запрос в SQL"
Нет. |
|||
46
MadJhey
22.10.15
✎
17:25
|
(45) давай примеры. Хотелось бы конкретики. Пока те запросы, которые парсил, все было вложенными.
|
|||
47
H A D G E H O G s
22.10.15
✎
17:27
|
(46) Оперативные остатки.
|
|||
48
MadJhey
22.10.15
✎
17:27
|
Кстати ссылка.ссылка добавляет лишнее соединение.
exec sp_executesql N'SELECT T1._Fld4956RRef, T1._Fld4957, T1._Fld4953, T1._Fld4952RRef, T1._Fld4958, T2._IDRRef, T1._Fld4960, T3._IDRRef FROM _Document193_VT4950 T1 WITH(NOLOCK) LEFT OUTER JOIN _Document193 T2 WITH(NOLOCK) ON T1._Document193_IDRRef = T2._IDRRef LEFT OUTER JOIN _Enum395 T3 WITH(NOLOCK) ON T1._Fld4959RRef = T3._IDRRef WHERE (T2._IDRRef IN (@P1))',N'@P1 varbinary(16)',0x837908606E6E76BD11E3BB0E91DABDE9 exec sp_executesql N'SELECT T1._Fld4956RRef, T1._Fld4957, T1._Fld4953, T1._Fld4952RRef, T1._Fld4958, T1._Document193_IDRRef, T1._Fld4960, T2._IDRRef FROM _Document193_VT4950 T1 WITH(NOLOCK) LEFT OUTER JOIN _Enum395 T2 WITH(NOLOCK) ON T1._Fld4959RRef = T2._IDRRef WHERE (T1._Document193_IDRRef IN (@P1))',N'@P1 varbinary(16)',0x837908606E6E76BD11E3BB0E91DABDE9 |
|||
49
MadJhey
22.10.15
✎
17:33
|
(46)
ВЫБРАТЬ Первые 10 ОстаткиТоваровОстатки.КоличествоОстаток, ОстаткиТоваровОстатки.Товар ИЗ РегистрНакопления.ОстаткиТоваров.Остатки КАК ОстаткиТоваровОстатки exec sp_executesql N'SELECT TOP 10 T1.Fld21Balance_, T1.Fld20RRef FROM (SELECT T2._Fld20RRef AS Fld20RRef, CAST(SUM(T2._Fld21) AS NUMERIC(30, 8)) AS Fld21Balance_ FROM _AccumRgT22 T2 WITH(NOLOCK) WHERE T2._Period = P1 GROUP BY T2._Fld20RRef HAVING (CAST(SUM(T2._Fld21) AS NUMERIC(30, 8))) <> @P2) T1',N'P1 datetime2(3),@P2 numeric(10)','5999-11-01 00:00:00',0 |
|||
50
H A D G E H O G s
22.10.15
✎
17:46
|
(49) Да, я ошибся.
|
|||
51
bolobol
22.10.15
✎
18:10
|
(49) А можно вопрос специалисту по виртуальным таблицам тут задать? Почему следующая конструкция даёт некорректные результаты:
ВЫБРАТЬ ОстаткиТоваровОстатки.КоличествоОстаток ИЗ РегистрНакопления.ОстаткиТоваров.Остатки КАК ОстаткиТоваровОстатки ВНУТРЕННЕЕ СОЕДИНЕНИЕ РегистрНакопления.ОстаткиТоваров.Остатки КАК ОстаткиТоваровОстатки1 ПО ОстаткиТоваровОстатки.Остаток <> ОстаткиТоваровОстатки1.Остаток ? |
|||
52
sash-ml
22.10.15
✎
18:16
|
что значит некорректные результаты, тут практически полное соединение
|
|||
53
bolobol
22.10.15
✎
18:27
|
(52) Вот-вот, а в результат только одна строка выходит...
|
|||
54
MadJhey
22.10.15
✎
22:00
|
(51) бред какой то. Цель то какая
|
|||
55
bolobol
23.10.15
✎
11:29
|
(54) Цель: получить все остатки, где результатов более одного в интересующем разрезе.
|
|||
56
mistеr
23.10.15
✎
14:56
|
(55) Чего?
|
|||
57
bolobol
23.10.15
✎
15:10
|
(56) Что "чего"?
|
|||
58
asady
23.10.15
✎
15:11
|
(57) в (51) реальный запрос?
|
|||
59
bolobol
23.10.15
✎
15:16
|
(58) О, нет конечно. Там и параметры виртуальные и соединения ПО (ресурс слева меньше нуля, справа больше нуля и наоборот) и равенство субконто1 и организации.
в (51) вопрос озвучен с точки зрения технологии его обработки системой, т.к. кроме одной строки в результат ничего не даёт, там где должно быть всё, что имеет соединение. Если в выборку добавить из второй таблицы данные (ОстаткиТоваровОстатки1.КоличествоОстаток) - то тогда результат верный. Без выборки данных из второй таблицы - одна случайная строка всегда постоянная... |
Форум | Правила | Описание | Объявления | Секции | Поиск | Книга знаний | Вики-миста |