Добро пожаловать в форум, Guest >> Войти | Регистрация | Поиск | Правила | | В избранное | Подписаться | ||
Все форумы / Microsoft SQL Server |
![]() ![]() |
Топик располагается на нескольких страницах: [1] 2 вперед Ctrl→ все |
Mike_za Member Откуда: Москва Сообщений: 1176 |
Есть запрос. Если из него убрать перекладку во временную таблицу, то 1.141 чтение превращаются в 76.248 select [Document].[ID] as [ID] ,[ВБ].[code] as [ВБ.Code] ,[ВБ].[Name] as [ВБ.Name] ,[Адм].[Name] as [Адм.Name] ,[Адм].[code] as [Адм.Code] ,[Адм].[Code_w_Budget] as [Адм.Code_w_Budget] ,[РзПр].[code] as [РзПр.Code] ,[РзПр].[Name] as [РзПр.Name] ,[ЦСР].[Name] as [ЦСР.Name] ,[ЦСР].[Code_w_Budget] as [ЦСР.Code_w_Budget] ,[ЦСР].[code] as [ЦСР.Code] ,[ВР].[Name] as [ВР.Name] ,[ВР].[code] as [ВР.Code] ,[Document].[Status] as [Document_Status] ,[Document].[docflow_Status_ID] as [docflow_Status_ID] ,case when [ЦСР].[CSR2005_ID] is null and coalesce(null,[Document].[CSR2005_ID]) is not null then cast(1 as bit) when [ВР].[VR_ID] is null and coalesce(null,[Document].[VR_ID]) is not null then cast(1 as bit) when [ВБ].[EL_ID] is null and coalesce(null,[Document].[EL_ID]) is not null then cast(1 as bit) when [РзПр].[RzPr_ID] is null and coalesce(null,[Document].[RzPr_ID]) is not null then cast(1 as bit) when [Адм].[GRBS_ID] is null and coalesce(null,[Document].[GRBS_ID]) is not null then cast(1 as bit) else cast(0 as bit) end as Is_Virtual_Row into [##Temp_GetFormDatacc128913c34a45d59769935ec1d584e9] from #global_p_Get_Form_Data__FormVariants as TFV inner join data.[Form_65112_2013_01_01_Document] as Document on Document.FormVariant_ID = TFV.ID left join spr.[ifn_GRBS](@StartDate, @EndDate, @Variant_ID) as [Адм] on [Document].[GRBS_ID] = [Адм].[GRBS_ID] left join spr.[ifn_EL](@StartDate, @EndDate, @Variant_ID) as [ВБ] on [Document].[EL_ID] = [ВБ].[EL_ID] left join spr.[ifn_VR](@StartDate, @EndDate, @Variant_ID) as [ВР] on [Document].[VR_ID] = [ВР].[VR_ID] left join spr.[ifn_RzPr](@StartDate, @EndDate, @Variant_ID) as [РзПр] on [Document].[RzPr_ID] = [РзПр].[RzPr_ID] left join spr.[ifn_CSR2005](@StartDate, @EndDate, @Variant_ID) as [ЦСР] on [Document].[CSR2005_ID] = [ЦСР].[CSR2005_ID] left join docflow.State as docflow_State on docflow_State.ID = Document.docflow_Status_ID option(maxdop 1, recompile) К сообщению приложен файл (Y.sqlplan - 149Kb) cкачать ![]() |
30 июн 15, 20:05 [17834735] Ответить | Цитировать Сообщить модератору |
Mike_za Member Откуда: Москва Сообщений: 1176 |
не влазят( https://yadi.sk/d/mo6zTGy0haezS |
30 июн 15, 20:09 [17834742] Ответить | Цитировать Сообщить модератору |
Mike_za Member Откуда: Москва Сообщений: 1176 |
Microsoft SQL Server 2014 - 12.0.2254.0 (X64) Jul 25 2014 18:52:51 Copyright (c) Microsoft Corporation Enterprise Edition (64-bit) on Windows NT 6.3 <X64> (Build 9600: ) (Hypervisor) |
30 июн 15, 20:10 [17834746] Ответить | Цитировать Сообщить модератору |
Mike_za Member Откуда: Москва Сообщений: 1176 |
собственно вопрос. ПОЧЕМУ?! |
30 июн 15, 20:18 [17834780] Ответить | Цитировать Сообщить модератору |
AnyKey45 Member Откуда: Ekaterinburg-Moscow-EU Сообщений: 219 |
А если убрать сортировку из того плана, который не вставляет во временную? Чтобы запросы отличались только наличием временной таблицы.... |
||
1 июл 15, 09:33 [17835921] Ответить | Цитировать Сообщить модератору |
SomewhereSomehow Member Откуда: Moscow Сообщений: 2480 Блог |
Добрый день. Согласно приведенному queryanalysis, у вас такая ситуация. ![]() Т.е. в запросе с SELECT INTO меньше логических чтений (как вы и написали в сообщении). Почему тогда вопрос о том, то он что-то портит? Либо вы опечатались, либо расшифруйте что значит «портит». О разнице чтений Если посмотреть на статистику чтений по таблицам, то видны четыре таблицы, в которых чтения различаются на порядок. Возьмем самую большую разницу, это таблица CSR2005_Vers (выделил красным). Если посмотреть на план, то видно, что в одном случае он выбирает сканирование, а в другом Seek+Lookup. Чтобы избавиться от Lookup нужно добавить в индекс [CSR2005_Vers].[UK_spr_CSR2005_Vers__CSR2005_ID_StartDate_Variant_ID] недостающие поля, все или какие-то из Code, Name, EndDate. О разнице в планах Следующий вопрос, резонно возникает, почему планы отличаются. Короткий ответ – потому, что разные запросы. Когда запросы отличаются – отличается дерево логических операторов, с которого начинается оптимизация. Далее, в процессе оптимизации сервер путем преобразований этого дерева может свести разные запросы к одному плану, но никто этого не гарантирует, т.к. ограничены и правила преобразования и время на их применение. Чем сложнее запрос, тем больше вариантов и тем меньше вероятность получить одинаковые планы для разных (хотя отличия минимальны) запросов. Несмотря на то, что сам запрос у вас не слишком сложный. В нем используются inline функции. Текст в таких функциях разворачивается в запрос, и запрос подставляется в основной запрос. Попробуйте представить, что вы взяли код всех функций и поместили его вместо них в запрос – вот какого монстрика должен оптимизировать сиквел. В итоге, в вашем запросе я засчитал 26 таблиц и соединений! Самым правильным было бы разбить запрос на подзапросы, с сохранением промежуточных результатов во временную таблицу. Но, судя по времени выполнения, у вас он и так работает быстро, так что решайте сами. Самое интересное, если посмотреть внимательно на запрос без временной таблицы, то можно увидеть, что он отличается тем, что в нем есть требование сортировки. select left join docflow.State as docflow_State on docflow_State.ID = Document.docflow_Status_ID order by [Document].[ID] option(maxdop 1, recompile) select into left join docflow.State as docflow_State on docflow_State.ID = Document.docflow_Status_ID option(maxdop 1, recompile) Вполне возможно, если вы его уберете, то планы станут различаться меньше или различий вообще не будет, за исключением помещения во временную таблицу. Это не гарантируется по озвученным выше причинам, но совершенно точно дополнительное требование сортировки сильно влияет на план, заставляя выбирать другие типы соединений, порядок и т.д. Так что сравнивать два разных, по сути, запроса некорректно. |
1 июл 15, 09:52 [17836000] Ответить | Цитировать Сообщить модератору |
Mike_za Member Откуда: Москва Сообщений: 1176 |
Да, я наоборот написал. Про сортировку, мне казалось, что она не влияла совсем, но я еще раз проверю. Как вы уже могли догадаться, этот запрос генерится в результате склейки, и оптимизировать чисто под него (индексы) возможности совсем нет, там уже другие функции и опорные таблицы. Непонятность ситуации для меня в том, что у меня несколько таких запросов, стабильно ухудшающихся после убирания времянки. Может быть есть какая-то специфика работы оптимизатора, при использовании "селект инто", влияющего на план? |
||
1 июл 15, 10:30 [17836201] Ответить | Цитировать Сообщить модератору |
смотрю_тут Member Откуда: Сообщений: 1368 |
это актуальные планы или оценочные планы до выполнения? |
||||
1 июл 15, 10:47 [17836307] Ответить | Цитировать Сообщить модератору |
Mike_za Member Откуда: Москва Сообщений: 1176 |
смотрю_тут, Актуальные |
1 июл 15, 10:49 [17836326] Ответить | Цитировать Сообщить модератору |
смотрю_тут Member Откуда: Сообщений: 1368 |
посмотрите оценочные, там разница есть? а так вам уже ответили, что запросы разные, да и не простые, |
||
1 июл 15, 11:12 [17836484] Ответить | Цитировать Сообщить модератору |
Mike_za Member Откуда: Москва Сообщений: 1176 |
смотрю_тут, не совсем понял. что значит оценочные? если речь о совпадении оценочного и реального количества строк, то оно практически совпадают в обоих планах. К сообщению приложен файл. Размер - 86Kb |
1 июл 15, 13:23 [17837615] Ответить | Цитировать Сообщить модератору |
Mike_za Member Откуда: Москва Сообщений: 1176 |
1. Убрал сортировки в обоих запросах с Into быстро - как и было, c селектом по прежнему плохо 2. Поставил сортировки в обоих вариантах количество чтений стало полностью одинаковое 3. Выкусил запрос из процедуры во всех вариантах стабильно плохой план Все три вызова выполняют из-под студии. 1 и 2 - вызов процедуры 3 - вызов уже склеенного запроса из статики. из динамики точно так же. т.е. более удачный план получается только при соблюдении условий: перекладка нет сортировки выполняется из недр процедуры |
1 июл 15, 13:27 [17837657] Ответить | Цитировать Сообщить модератору |
AnyKey45 Member Откуда: Ekaterinburg-Moscow-EU Сообщений: 219 |
покажите планы без сортировки, интересно насколько они отличаются |
||
1 июл 15, 13:36 [17837751] Ответить | Цитировать Сообщить модератору |
Mike_za Member Откуда: Москва Сообщений: 1176 |
оптимизатор правильно оценивает количество строк, но круто промахивается с EstIO cost. Ну или это издержки студии сортируем по количеству чтений, 2 верхних https://yadi.sk/d/FF547XZChbVjm К сообщению приложен файл. Размер - 67Kb |
1 июл 15, 13:49 [17837876] Ответить | Цитировать Сообщить модератору |
SomewhereSomehow Member Откуда: Moscow Сообщений: 2480 Блог |
Это DML инструкция и оптимизируется она как DML. Но каких-то специфичных требований в отличие от других DML (типа insert, delete), например, таких как: DML Request Sort, Halloween protection, проверка Constraint и FK, identity generation и т.д. - для select into не предъявляется илимне о них неизвестно. Но потенциально они возможны, т.к. повторюсь еще раз, это DML, нельзя исключить каких-то внутренних недокументированных оптимизаций, плюс то, о чем я писал ранее про разные исходные деревья операторов.
Интересно, потому что в теории должно быть наоборот. При вставке требование order by как правило исключается (если не требуете, например, генерации identity в определённом порядке). Возможно, в случае сложного запроса этого не происходит - тогда это баг. Было бы интересно сделать репро... Я смотрю, у вас есть возможность делать queryanalysis файлы. Приложите три файла ко всем своим трем экспериментам, чтобы можно было увидеть планы, время и чтения. П.С. Кстати, то что вы называете "плохо" - имеется ввиду медленно? Или по количеству чтений? Просто у вас один запрос выполняется 500 мс, другой 200 мс - т.е. оба достаточно быстро, учитывая их сложность. И как меряете время, не включается ли туда клиентский вывод? В бесплатной версии Plan Explorer время duration меряется при помощи set statistics time on, которая включает время вывода на клиент, которое разумеется будет больше, ведь вы возвращаете строки. |
||||
1 июл 15, 14:20 [17838109] Ответить | Цитировать Сообщить модератору |
Mike_za Member Откуда: Москва Сообщений: 1176 |
не совсем понял. сортировка есть в плане и в простом случае К сообщению приложен файл. Размер - 94Kb |
||
1 июл 15, 15:14 [17838556] Ответить | Цитировать Сообщить модератору |
Mike_za Member Откуда: Москва Сообщений: 1176 |
Ранее сразу по завершении процедуры клиент делал селект из времяки. Сия ситуация возникла при попытке оптимизации, заключающейся в удалении перекладки во времяку. В итоге я второй день нахожусь в неком смятении, ибо в результате такой оптимизации получил дикий рост чтений))))) да, к перекладке надо досумировать время выбоки уже из времянки. (Plan Explorer пишет 129 мс. Но чтений то всего 196) планы по моим 3м вариантом, сейчас подготовлю. |
||
1 июл 15, 15:24 [17838635] Ответить | Цитировать Сообщить модератору |
SomewhereSomehow Member Откуда: Moscow Сообщений: 2480 Блог |
Mike_za,create database dbsort; go use dbsort; go create table t(a int); go alter database dbsort set compatibility_level = 100; go set showplan_xml on go select * into #t from t order by a; go set showplan_xml off go alter database dbsort set compatibility_level = 110; go set showplan_xml on go select * into #t from t order by a; -- no sort go set showplan_xml off go use master; go drop database dbsort; Уровень совместимости БД какой у вас? 2008 что ли? Я думал, раз сервер 2014, то уровень совместимости хотя бы предыдущий. В 2008 да, лишняя сортировка присутствовала. |
1 июл 15, 15:33 [17838674] Ответить | Цитировать Сообщить модератору |
Mike_za Member Откуда: Москва Сообщений: 1176 |
https://yadi.sk/d/6xvnpgz7hbfhv |
1 июл 15, 15:34 [17838677] Ответить | Цитировать Сообщить модератору |
Mike_za Member Откуда: Москва Сообщений: 1176 |
SomewhereSomehow, да, уровень совместимости действительно 2008. |
1 июл 15, 15:37 [17838699] Ответить | Цитировать Сообщить модератору |
SomewhereSomehow Member Откуда: Moscow Сообщений: 2480 Блог |
Mike_za, Ну смотрите, в вашем выложенном queryanalisys, второй файл "2 - сортировка", про который вы писали:
Результат
В обоих запросах. Против 1 141 чтений изначально. Т.е. когда сортировка есть - все-таки плохо обоим запросам, так получается? (если мы берем за критерий "плохости" кол-во чтений). Т.е. утверждение про количетсов чтений, которое стало одинаково, имеет негативный оттенок - т.е. стало одинаково много. Вы лучше поясняйте дополнительно для тупых, типа меня. А то же ведь воспринимается, что добавил сортировку - стало всем хорошо, т.к. количество чтений совпало (подразумевая, что совпало с малым числом). Все, план с сортировкой понятен - его отринули. Далее, интересен план без сортировки. Я попробовал изучить различия. Но что меня насторожило, это разное число строк из таблиц: ![]() Еще одно: ![]() Не разные ли условия? Предикаты? Наполнение временных таблиц? |
||||||
1 июл 15, 23:57 [17840688] Ответить | Цитировать Сообщить модератору |
Mike_za Member Откуда: Москва Сообщений: 1176 |
SomewhereSomehow, большое спасибо за проявленное участие))
ну я подумал, что не совсем точно описал, и специально в резюме подитожил
на момент теста условия должны были быть одинаковые. там же разные алгоритмы соединения, в итоге выходил одинаковое число строк (скриншот). ПС У наших инлайновых функций жуткое содержимое (очередной костыль с версионностью), еще они вложены друг в друга
К сообщению приложен файл. Размер - 56Kb |
|||||||
2 июл 15, 14:13 [17843554] Ответить | Цитировать Сообщить модератору |
SomewhereSomehow Member Откуда: Moscow Сообщений: 2480 Блог |
Mike_za, Ну, если вы говорите, что все данные и параметры одинаковые, и влияет именно перекладывание во временную таблицу - то кейс интересный. В простых случаях такого изменения планов не происходит. Одно объяснение - это то, что я давал выше про разные деревья и ограниченность оптимизации ресурсами. Если вы посмотрите, то у обоих планов: ![]() Который с SELECT тоже (скрин выкладывать не буду, кому интересно - могут посмотреть сами в приложенных ТС файлах). Timeout значит, что было исчерпано количество шагов отведенное на оптимизацию и был возвращен наиболее дешевый план на этот момент. Учитывая, что оба запроса начинают с разных деревьев, вполне возможно, что к моменту таймаута они приходят к разным плана, и один из них оказывается более удачным, чем другой. Можете глянуть мои статьи, про "ослабление" таймаута: Оптимизатор без границ (ч.1) Оптимизатор без границ (ч.2) И в порядке эксперимента (не используйте это на регулярной основе на боевом сервере), включить упомянутые в статье флаг и посмотреть: - будет ли таймаут (т.к. полностю его отключить нельзя, он ограничен 3 072 000 преобразованиями в текущей версии) - если не будет, то придут ли разные запросы к одинаковым или близким по чтениям планам. Если таймаута в 3 072 000 операций не будет, а планы все равно сильно отличаются, значит действуют какие-то правила/эвристики о которых мы не знаем. Это возможно по причинам озвученным ранее про DML, если так, то кейс все еще интересный. Отпишитесь по результатам эксперимента. Можно пытаться сделать репро. В целом, насколько я вижу, оба запроса выполняются вполне себе быстро (200 мс и 500 мс). Так что, видимо, интерес чисто академический. Если дело не в разных деревьях - то мне тоже было бы интересно докопаться до сути. П.С. Я уезжаю в отпуск с завтра на две недели. По возможности постараюсь следить за темой, но не обещаю, что это будет оперативно. С вас - эксперимент с таймаутом =) И спасибо за хороший и грамотно оформленный вопрос =) |
2 июл 15, 19:31 [17845420] Ответить | Цитировать Сообщить модератору |
Mike_za Member Откуда: Москва Сообщений: 1176 |
SomewhereSomehow,
Я тоже думал в эту сторону, но про флаги не знал. Завтра попробую. Еще есть мысль, создать предварительно таблицу и обойтись без ддл |
||
2 июл 15, 21:41 [17845866] Ответить | Цитировать Сообщить модератору |
Mike_za Member Откуда: Москва Сообщений: 1176 |
SomewhereSomehow, ваши предположения полностью подтвердились)) Отключение таймаута привело к одинаковым хорошим планам. ДАЖЕ ПРИ ВКЛЮЧЕННОЙ СОРТИРОВКЕ!
К сожалению не академический))) На определенной операции таких селектов может быть достаточно много. Выгребаются документы из кучи временных периодов и разных хранилищ и между ними производится контроль. + я то провожу тесты на 12 процессорном с кучей памяти монстре, а у клиентов наших дикий зоопарк... Но в процессе эксперимента несколько раз переставил строиться хороший план и со вставкой во времянку. Помогли пересчет статистики, очистка кеша и тп... Так что в итоге поведение со вставкой не детерминировано, и надо что-то думать нам будет дальше с кешем функции
|
|||
3 июл 15, 14:40 [17849009] Ответить | Цитировать Сообщить модератору |
Топик располагается на нескольких страницах: [1] 2 вперед Ctrl→ все |
Все форумы / Microsoft SQL Server | ![]() |