Имя: Пароль:
1C
1С v8
Как оптимизировать запрос...
0 Ministr
 
18.06.14
12:42
Привет, всем! В УПП - есть регистр сведений "Версии объектов", измерение "Объект" - составной тип содержит все справочники и все  документы. Необходимо выбрать версии по определенным типам объекта. Я написал следующий запрос..:

ВЫБРАТЬ
    ВерсииОбъектов.Объект,
    ВерсииОбъектов.НомерВерсии,
    ВерсииОбъектов.ВерсияОбъекта,
    ВерсииОбъектов.АвторВерсии,
    ВерсииОбъектов.ДатаВерсии
ИЗ
    РегистрСведений.ВерсииОбъектов КАК ВерсииОбъектов
ГДЕ
    (ВерсииОбъектов.Объект ССЫЛКА Документ.ВводНачальныхОстатковОС
            ИЛИ ВерсииОбъектов.Объект ССЫЛКА Документ.ИзменениеСпособовОтраженияРасходовПоАмортизацииОС
            ИЛИ ВерсииОбъектов.Объект ССЫЛКА Документ.КорректировкаЗаписейРегистров
            ИЛИ ВерсииОбъектов.Объект ССЫЛКА Документ.ПринятиеКУчетуОС)

Как сделать более оптимально?
Недавно прочитал статью про составной тип данных - понял, что при неумелом пользовании в запросах.. можно дорого заплатить по времени)
1 Fragster
 
гуру
18.06.14
12:44
посмотри профайлером, что там на выходе получается. по идее может быть замена на ТИП и/или на Объединить, если кривота.
2 Ministr
 
18.06.14
12:46
(1) не хочу даже уточнять, потому что мне это ничего не говорит... нет , случайно статьи про, то как смотреть профайлы и прочее...
3 H A D G E H O G s
 
18.06.14
12:46
(2) Есть гугл.
4 H A D G E H O G s
 
18.06.14
12:47
(0) А что не так работает?
5 МихаилМ
 
18.06.14
12:47
нормальный запрос, если по полю Объект есть подходящий индекс
6 H A D G E H O G s
 
18.06.14
12:47
(5) Автор может выгружать результат в ТЗ, например, или выводить на экран.
7 Ministr
 
18.06.14
12:47
(3) Согласен
8 Fragster
 
гуру
18.06.14
12:50
(5) индекс-то есть, только он составной из 3-х (в данном случае) полей (на вопрос, почему для составных полей только ссылочных типов не использовать 2 колонки, мне никто не ответил).
вопрос в том, как парсер 1сный делает "ИЛИ" для отбора по первым двум колонкам из трех. может быть банальная штука с заменой ИЛИ на Объединить все поможет в случае, если запрос криво преобразуется. А если не криво - то ничего не поможет.
9 Ministr
 
18.06.14
12:51
(5) Я один раз таблицу сформирую в начале функции с помощью запроса, потом по ней с помощью отбора в цикле уже буду находить нужные мне данные.
10 Fragster
 
гуру
18.06.14
12:51
а смотреть в профайлер мне лень.
11 H A D G E H O G s
 
18.06.14
12:51
(10) Я посмотрю, но думаю, проблема (а ведь мы про нее даже не услышали) - в постобработке
12 Крошка Ру
 
18.06.14
12:54
(0)
ВЫБРАТЬ
  ВЫБОР
     КОГДА ВерсииОбъектов.Объект ССЫЛКА Документ.ПринятиеКУчетуОС
     ТОГДА ВЫРАЗИТЬ(ВерсииОбъектов.Объект КАК Документ.ПринятиеКУчетуОС
     КОГДА ВерсииОбъектов.Объект ССЫЛКА Документ..... и т.д.
  КОНЕЦ КАК Док1
13 Fragster
 
гуру
18.06.14
12:58
(12) мимо
14 Крошка Ру
 
18.06.14
12:59
(13) ???

Мы в морской бой играем?
15 Maxus43
 
18.06.14
13:01
(14) попал!
16 Maxus43
 
18.06.14
13:03
можно поидее ГДЕ ТИПЗНАЧЕНИЯ(Объект) В (&ТИПЫ)

но опять же надо смотреть во что превратится в скуле
17 DexterMorgan
 
18.06.14
13:04
Поддерживаю (12), эта рекомендация еще Рупасова в статье на kb по оптимизации запросов
18 Широкий
 
18.06.14
13:06
У тебя проблема не в составном типе а в условии "ИЛИ" - оно не дает индексу в полную силу работать.
Если записей ну очень много - можно сделать запрос из 4 объединений по каждому виду документа
19 Maxus43
 
18.06.14
13:06
(17) эта хрень нужна когда ты из поля составного типа хочешь вытащить реквизит объекта. Простое приведение к типу самого поля почти ниячего не даст, только уменьшит количество типов на выходе в колонке, но оно так и будет составным
20 DexterMorgan
 
18.06.14
13:07
(19) ну их же будет меньше
21 Fragster
 
гуру
18.06.14
13:07
(20) и что?
22 Широкий
 
18.06.14
13:07
(17) Он не получает же из документов какую то инфу. Выразить то зачем?
23 H A D G E H O G s
 
18.06.14
13:09
clustered index seek. Расслабьтесь.
24 Maxus43
 
18.06.14
13:10
(20) технически разницы нет, что 5 типов, что 150. Разница только при обращении к реквизитам, а тут такой задачи нет, и все реверансы эти бессмысленны...
25 DexterMorgan
 
18.06.14
13:10
(18) Да кстати, вместо или можно попробовать использовать объединение
26 H A D G E H O G s
 
18.06.14
13:11
(19) (19) Эта хрень нужна, чтобы сервер 1С не задумывался на пару секунд при первом выполнении запроса при получении составного реквизита.

Именно сервер 1С.
27 H A D G E H O G s
 
18.06.14
13:11
(25) Кхм-кхм. см (23). Курим. Ждем автора.
28 Maxus43
 
18.06.14
13:13
(26) в данном конкретном случае. При получении реквизита она нужна для другого, чтоб ненужные соединения со всеми типами не делать
29 H A D G E H O G s
 
18.06.14
13:14
(28) Спс, кэп.
30 Широкий
 
18.06.14
13:14
(23) Проверял? Может все-таки scan?
31 Maxus43
 
18.06.14
13:15
(29) дак ты как будто бы опроверг про "реквизиты", и автор может подумать лишнего)
32 H A D G E H O G s
 
18.06.14
13:15
(30) Проверял. 1С не тупее паровоза.
WHERE ((((T1._Fld24334_TYPE = 0x08 AND T1._Fld24334_RTRef = 0x00000104) OR (T1._Fld24334_TYPE = 0x08 AND T1._Fld24334_RTRef = 0x00000147)) OR (T1._Fld24334_TYPE = 0x08 AND T1._Fld24334_RTRef = 0x0000015F)) OR (T1._Fld24334_TYPE = 0x08 AND T1._Fld24334_RTRef = 0x000001C8))

keyword:

T1._Fld24334_TYPE = 0x08
33 Крошка Ру
 
18.06.14
13:17
(25) Разница в том, что у тебя в запросе будет левое соединение с таблицами ВСЕХ типов составного объекта или только те, которые мы явно укажем. А уж обращаемся мы к реквизиту объекта или нет - без разницы
34 Крошка Ру
 
18.06.14
13:17
(33) к (24)
35 Fragster
 
гуру
18.06.14
13:17
(33) откуда там будет соединение-то?
36 Широкий
 
18.06.14
13:18
(32) Ты план запроса смотри
37 Широкий
 
18.06.14
13:19
+36 а лучше покажи
38 Maxus43
 
18.06.14
13:19
(33) не будет никаких соединений без залезания "внутрь" составного типа за реквизитом
39 Крошка Ру
 
18.06.14
13:20
(35) Хотя вообще, да, из регистра же данные тащим
41 H A D G E H O G s
 
18.06.14
13:24
StmtText                                                                          
Clustered Index Seek(OBJECT:([database].[dbo].[_InfoRg24333].[_InfoR24333_ByDims_RN] AS [T1]), SEEK:([T1].[_Fld24334_TYPE]=0x08 AND [T1].[_Fld24334_RTRef]=0x00000104 OR [T1].[_Fld24334_TYPE]=0x08 AND [T1].[_Fld24334_RTRef]=0x00000147 OR [T1].[_Fld24334_TYPE]=0x08 AND [T1].[_Fld24334_RTRef]=0x0000015F OR [T1].[_Fld24334_TYPE]=0x08 AND [T1].[_Fld24334_RTRef]=0x000001C8) ORDERED FORWARD)
42 Жан Пердежон
 
18.06.14
13:26
а где вариант с ОБЪЕДИНИТЬ ВСЕ?
43 Широкий
 
18.06.14
13:26
(41) Тогда все, в (0) запрос уже оптимален
44 MrStomak
 
18.06.14
13:34
(41) Ты понимаешь, что индекс здесь используется по признаку Ссылка, а не по признаку Документ.чтото ?
45 H A D G E H O G s
 
18.06.14
13:37
(44) Чего?
46 H A D G E H O G s
 
18.06.14
13:38
(44) Я не понял твоего каммента.
47 Fragster
 
гуру
18.06.14
13:38
(45) MrStomak просто не в курсе, как хранятся данные в базе 1с и какие там индексы
48 MrStomak
 
18.06.14
13:47
(47) В курсе
(46) Из твоего поста я понял (32), что используется предикат по полю T1._Fld24334_TYPE в физическом операторе. Это был бы частичный поиск по индексу, так как нужно использование двух полей. Проверил сам - в предикатах поиска присутствует также второе поле.
49 H A D G E H O G s
 
18.06.14
13:52
(48)
Ты очень сложно выражаешь свои мысли. Давай я проще:

1С наложила условие на Класс метаданных (справочник/документ/ПВХ/БизнесПроцесс) и на тип класса метаданных (Документ.ВводОстатков/Документ.РТУ).
И это прекрасно.

Не наложи она условия на Класс метаданных  (_Fld24334_TYPE]=0x08)

индекс бы пошел лесом.
50 H A D G E H O G s
 
18.06.14
13:58
Понапридумывали тут.. (ворчит)

http://www.sql.ru/articles/mssql/2007/012302seekpredicates.shtml

Для следующих ниже примеров, мы можем использовать индекс для удовлетворения условий предиката для столбца "a", но не для столбца "b". В этих случаях потребуется остаточный предикат:

a > 100 and b > 100 a like 'abc%' and b = 2
51 H A D G E H O G s
 
18.06.14
13:59
"потребуется остаточный предикат"
Объясните мне, как это по русски.

indexseek+indexscan?

как это выглядит в профайлере?
52 H A D G E H O G s
 
18.06.14
14:00
Вот так правильно условия:

a > 100 and b > 100

a like 'abc%' and b = 2
53 MrStomak
 
18.06.14
14:00
(51) В профайлере это выглядит как разделение в тексте плана запроса SEEK и WHERE, но всё это будет index seek
54 MrStomak
 
18.06.14
14:02
(49) Если преобразовать текст запроса из (0) так:
ВЫБРАТЬ
    ВерсииОбъектов.Объект,
    ВерсииОбъектов.НомерВерсии,
    ВерсииОбъектов.ВерсияОбъекта,
    ВерсииОбъектов.АвторВерсии,
    ВерсииОбъектов.ДатаВерсии
ИЗ
    РегистрСведений.ВерсииОбъектов КАК ВерсииОбъектов
ГДЕ
    (ВерсииОбъектов.Объект ССЫЛКА Документ.ВводНачальныхОстатковОС
            ИЛИ ВерсииОбъектов.Объект ССЫЛКА Документ.ИзменениеСпособовОтраженияРасходовПоАмортизацииОС
            ИЛИ ВерсииОбъектов.Объект ССЫЛКА Документ.КорректировкаЗаписейРегистров
            ИЛИ ВерсииОбъектов.Объект ССЫЛКА Документ.ПринятиеКУчетуОС
            или версииобъектов.объект = значение(Документ.ПринятиеКУчетуОС.ПустаяСсылка))

,то тоже будет Index seek, тоже будут в условии запроса все поля, но при этом будет использоваться только индекс по первому полю TYPE. Я из твоего поста подумал, что именно это и произошло.
55 H A D G E H O G s
 
18.06.14
14:03
(53) Счаст пытаюсь представить себе физический смысл "a > 100 and b > 100" для b дерева и не понимаю проблемы.
56 MrStomak
 
18.06.14
14:05
(55) Я не понял поста (52) Это к чему?
57 H A D G E H O G s
 
18.06.14
14:06
(56) Я слитно написал их, эти 2 варианта условий в (50), исправился.
58 MrStomak
 
18.06.14
14:11
(55) Как ты это сделаешь, кроме как сначала выбрав все записи где а>100, а потом, уже из них, где b>100?
59 H A D G E H O G s
 
18.06.14
14:16
(58) Индексное дерево для 2-х полей строится одно?
60 H A D G E H O G s
 
18.06.14
14:16
(58) Или для каждого поля - отдельное дерево. Для полей, в составном индексе.
61 MrStomak
 
18.06.14
14:19
(60) Как может быть несколько деревьев в индексе? Одно дерево.
62 H A D G E H O G s
 
18.06.14
14:21
Ядро СУБД Cach? использует B+-деревья для хранения данных...
После имени глобала в круглых скобках через запятую
указывается произвольное количество индексов. Компилятор осуществляет
преобразование всего множества индексов в ключ B+-дерева...

Вот.

Тоесть, при выполнении условия "a > 100 and b > 100", это условие должно преобразоваться в условие вида
"key>100"
63 H A D G E H O G s
 
18.06.14
14:22
И потом выполнить типовой поиск по B+ дереву.
64 H A D G E H O G s
 
18.06.14
14:23
Хотя нет.
65 H A D G E H O G s
 
18.06.14
14:24
Ключом B+ дерева тут будет скорее всего Структура с элементами
[a,b]

Или хэш.

Блин.
66 H A D G E H O G s
 
18.06.14
14:27
Нет. Нельзя хэш. Нам нужны исходные данные.
67 H A D G E H O G s
 
18.06.14
14:27
Например, для получения данных через индекс.
68 MrStomak
 
18.06.14
14:32
Хэш используется для соединений, в индексе мы последовательно сверяем куски известного ключа со значениями для каждой "развилки".
69 H A D G E H O G s
 
18.06.14
14:33
(68) Ты, скорее всего, меня не понял.
70 H A D G E H O G s
 
18.06.14
14:36
(68)

wiki:B-%E4%E5%F0%E5%E2%EE#mediaviewer/Файл:B-tree-definition.png

Что находиться в КЛЮЧЕ корневого узла k1, индексного дерева для полей а, b таблицы, в которой поле a имеет значения от 0 до 100, поле b имеет значение от 100 до 200.

Я вот думаю - там структура со значениями
50,100
71 H A D G E H O G s
 
18.06.14
14:38
72 MrStomak
 
18.06.14
14:49
(70) Почему 50,100? Там должна быть конкатенация значений всех ключей.
73 MrStomak
 
18.06.14
14:49
(70) Точнее, всех полей.
74 H A D G E H O G s
 
18.06.14
14:51
(72) как потом вытаскивать данные, ну, допустим при indexscan?
75 H A D G E H O G s
 
18.06.14
14:52
(72) Как сконкатенировать date и nvarchar?
76 MrStomak
 
18.06.14
14:52
(74) первые столько-то байт - первое поле, вторые столько-то байт - второе поле
77 H A D G E H O G s
 
18.06.14
14:53
(76) Тупо побайтовый набор? Это и есть Структура.
78 MrStomak
 
18.06.14
14:55
(77) я думал, у тебя 50,100 означало разные узлы, где значение только а, а не структуру со значениями а и б.
79 MrStomak
 
18.06.14
14:55
Ну да, так будет узел выглядеть, 50,100
80 H A D G E H O G s
 
18.06.14
14:56
(79) Отлично!
81 MrStomak
 
18.06.14
15:03
добравшись до узла , где a=100, мы знаем, что всё остальное точно удовлетворяет предикату a>100 и отбираем это. Если мы продолжаем поиск, и находим удовлетворение условию b>100, то это совсем не означает, что все остальные строки удовлетворяют этому условию! Потому что там дальше может быть а=110, б=2, следующая запись а=110 б = 112, потом опять а=111 б = 1. Дальше как ни крути, нужно выполнять скан всех строк индекса.
82 H A D G E H O G s
 
18.06.14
15:04
(81) Стоп. А разве дерево не отсортировано?
83 wade25
 
18.06.14
15:05
Соединяй правым соединение с таблицами этих документов, будет отбор на уровне SQL, отработает быстро.
84 MrStomak
 
18.06.14
15:05
(82) Отсортировано. Вот тебе порядок - 110 2, 110 112, 111, 1.
Это всё в порядке сортировки побайтовой конкатенации значений полей.
85 MrStomak
 
18.06.14
15:06
В B-дереве чтобы выполнять поиск по всем полям у нас необходимое условие, чтобы предикаты на все поля, кроме последнего, были на эквивалентность.
86 H A D G E H O G s
 
18.06.14
15:07
(84) таймаут! Пошел думать.
87 H A D G E H O G s
 
18.06.14
15:08
(84) Почему то мне кажется, что сортировка будет не по конкатенации байтов, а по значения полей.
88 H A D G E H O G s
 
18.06.14
15:08
а по значения полей.-> а по значениям полей.
89 MrStomak
 
18.06.14
15:08
(83) *грустно смотрит*
90 H A D G E H O G s
 
18.06.14
15:08
В корне у нас должны быть серединки диапазонов.
91 MrStomak
 
18.06.14
15:08
(88) какая разница?
92 H A D G E H O G s
 
18.06.14
15:09
Все. Это для меня слишком сложно. Мне нужно на бумажке начертить дерево и карандашиком поискать по нему.
93 wade25
 
18.06.14
15:10
(89) Пробовал, что бы критиковать? Мб не так причину скорости выполнения написал, но это работает ;)
94 MrStomak
 
18.06.14
15:10
(90) Ключ один, какие серединки?
95 MrStomak
 
18.06.14
15:10
(93) тут уже профайлером выяснили, что идет индекс сик по всем условиям.
96 H A D G E H O G s
 
18.06.14
15:11
(94) Ключ один физически, состоит из 2-х частей логически. Я же привел пример со структурой
[50,100]
97 MrStomak
 
18.06.14
15:11
(92) Не рассматривай а и б как разные ключи. Это один ключ, и он отсортирован.
98 H A D G E H O G s
 
18.06.14
15:12
50 - серединка диапазона [0..100] для поля a
100 - серединка диапазона [0..200] для поля b
99 H A D G E H O G s
 
18.06.14
15:13
(97) Тоесть, в корневом узле, значение ключа не [50,100] ?
100 MrStomak
 
18.06.14
15:13
(98) нету отдельного диапазона для поля б
101 MrStomak
 
18.06.14
15:14
(99) Наверху дерева первое значение, то есть 0,100
102 MrStomak
 
18.06.14
15:15
дальше узлы нормализованно распределяются
103 H A D G E H O G s
 
18.06.14
15:15
(100) При построении индекса - строится побайтовая конкатенация, сортируется, выбирается середина, ее значение записывается в структуру ключа корневого узла?
104 MrStomak
 
18.06.14
15:15
при этом вторая часть ключа нам бесполезна
105 H A D G E H O G s
 
18.06.14
15:16
(101) Посмотри на схемку http://commons.wikimedia.org/wiki/File:B-tree-definition.png#mediaviewer/Файл:B-tree-definition.png

Там в корневом узле - значение середины диапазона.
И алгоритм поиска - именно по тому, больше или меньше искомое значение значению ключа. В зависимости от этого - идем по нужным потомкам - ветвям.
106 MrStomak
 
18.06.14
15:20
(105) ты прав, там середина будет.
107 H A D G E H O G s
 
18.06.14
15:20
(106) Фух... Продолжим...
(103) - Это все так?
108 MrStomak
 
18.06.14
15:20
Ну и середина эта определяется как среденее значение сконкатенированного ключа.
109 MrStomak
 
18.06.14
15:21
Да
110 H A D G E H O G s
 
18.06.14
15:21
(108) Среднее значение или значение середины диапазона?
111 MrStomak
 
18.06.14
15:22
(1068) Запись за номером N/2 в отсортированном массиве, где N- число разных ключей.
112 MrStomak
 
18.06.14
15:23
Даже не разных, есть варианты неуникального индекса наверное.
113 H A D G E H O G s
 
18.06.14
15:24
(111) т.е. Значение середины диапазона. Ок.
114 H A D G E H O G s
 
18.06.14
15:24
(111) Вот теперь все ясно.
115 H A D G E H O G s
 
18.06.14
15:24
Вот теперь понятен смысл последующего indexscan по b>100 после indexseek по a>100
116 MrStomak
 
18.06.14
15:25
т.е. в корневом узле значение 50,100 может получиться при равномерном рампределении, т.е. одному ключу а соответствует уникальный ключ б.
117 H A D G E H O G s
 
18.06.14
15:25
Я думал, дерево отсортировано по значениям полей a и b, а не по их побайтовой конкатенации.
118 MrStomak
 
18.06.14
15:26
(116) Или там у тебя б=100 это начало диапазона.. Такое уже будет от везения зависеть.
119 MrStomak
 
18.06.14
15:28
(117) Ну так ты спросил вроде бы для этого - одно или несколько деревьев? Нельзя отсортировать один ключ двумя способами.
120 MrStomak
 
18.06.14
15:28
(119) Точнее, в один момент времени он будет отсортирован только одним образом.
121 H A D G E H O G s
 
18.06.14
15:28
(118) Это очень редкий шанс для больших таблиц.
122 H A D G E H O G s
 
18.06.14
15:30
(119) Я вообще не знал про физику хранения составных индексов.
123 Кир Пластелинин
 
18.06.14
15:36
мне кажется автор темы сейчас очень грустно на нее смотрит) ну и да - закладка.
124 H A D G E H O G s
 
18.06.14
15:44
Для (70) правка

поле b имеет значение от 100 до 200. ->

поле b имеет значение от 0 до 200.
125 Bober
 
18.06.14
15:56
(0) самый лучший вариант оптимизации это не выгребать в запросе поле версия объекта.
126 H A D G E H O G s
 
18.06.14
16:01
(125) Он и не выгребает.
127 H A D G E H O G s
 
18.06.14
16:01
1С не тупее паровоза.
128 Bober
 
18.06.14
16:02
(126) а это тогда кто ВерсииОбъектов.ВерсияОбъекта
129 H A D G E H O G s
 
18.06.14
16:11
(128) Это будет потом, скорее всего, при Хранилище.Получить().
130 Bober
 
18.06.14
16:12
(0) вторая проблема в том, что если это выводится в тз или еще как-то (не через СКД), то система будет делать запрос вида:
SELECT
T1._IDRRef,
T1._Number,
T1._Date_Time
FROM _Document128 T1 WITH(NOLOCK)
WHERE T1._IDRRef = P1

для получения представления для каждой ссылки.
131 Bober
 
18.06.14
16:12
(129) это идет сразу, если через запрос, то сервер 1с все это выгребает и преобразовывает с свои объекты.
132 H A D G E H O G s
 
18.06.14
16:22
(131) Да, ты прав, не заметил это поле в профайлере.
133 H A D G E H O G s
 
18.06.14
16:22
Но как бы, скорее всего, это то и нужно автору.
134 Bober
 
18.06.14
16:30
(133) если идет обработка в цикле версий, то скорее всего это сервисная обработка и вопрос скорости выполнения не стоял. Скорее всего это какой-то отчет или еще что-то.