|   |   | 
| 
 | Как оптимизировать запрос... | ☑ | ||
|---|---|---|---|---|
| 0
    
        Ministr 18.06.14✎ 12:42 | 
        Привет, всем! В УПП - есть регистр сведений "Версии объектов", измерение "Объект" - составной тип содержит все справочники и все  документы. Необходимо выбрать версии по определенным типам объекта. Я написал следующий запрос..:
 ВЫБРАТЬ ВерсииОбъектов.Объект, ВерсииОбъектов.НомерВерсии, ВерсииОбъектов.ВерсияОбъекта, ВерсииОбъектов.АвторВерсии, ВерсииОбъектов.ДатаВерсии ИЗ РегистрСведений.ВерсииОбъектов КАК ВерсииОбъектов ГДЕ (ВерсииОбъектов.Объект ССЫЛКА Документ.ВводНачальныхОстатковОС ИЛИ ВерсииОбъектов.Объект ССЫЛКА Документ.ИзменениеСпособовОтраженияРасходовПоАмортизацииОС ИЛИ ВерсииОбъектов.Объект ССЫЛКА Документ.КорректировкаЗаписейРегистров ИЛИ ВерсииОбъектов.Объект ССЫЛКА Документ.ПринятиеКУчетуОС) Как сделать более оптимально? Недавно прочитал статью про составной тип данных - понял, что при неумелом пользовании в запросах.. можно дорого заплатить по времени) | |||
| 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) если идет обработка в цикле версий, то скорее всего это сервисная обработка и вопрос скорости выполнения не стоял. Скорее всего это какой-то отчет или еще что-то.     | 
| Форум | Правила | Описание | Объявления | Секции | Поиск | Книга знаний | Вики-миста |