:: Не фоксом единым
Oracle. Использование индексов в join
Pekpytep
Автор

Сообщений: 727
Откуда: Луганск
Дата регистрации: 19.10.2010
Всем привет.
Имеется некий запрос вида
select ...
from departments de
join moves mo
on de.id_dept = nvl(mo.fid_new_dept, mo.fid_dept)
where...
План выполнения показывает, что не используется ни один из индексов по fid_new_dept и fid_dept.
Как лучше оптимизировать соединение таблиц, построив индекс по функции или попробовать переписать его к виду
select ...
from departments de
join moves mo
on de.id_dept = mo.fid_new_dept or de.id_dept = mo.fid_dept and mo.fid_new_dept is null
where...
?
Но всегда ли условия соединения проверяются в том же порядке, в каком они описаны?
Что посоветуете? Спасибо.



Исправлено 2 раз(а). Последнее : Pekpytep, 31.07.17 16:46
Ratings: 0 negative/0 positive
Re: Oracle. Использование индексов в join
PaulWist

Сообщений: 14601
Дата регистрации: 01.04.2004
Типа:

select ...
from departments de
join moves mo
on de.id_dept = mo.fid_new_dept
where...
union [all]
select ...
from departments de
join moves mo
on de.id_dept = mo.fid_dept
where...


------------------
Есть многое на свете, друг Горацио...
Что и не снилось нашим мудрецам.
(В.Шекспир Гамлет)
Ratings: 0 negative/0 positive
Re: Oracle. Использование индексов в join
Igor Korolyov

Сообщений: 34580
Дата регистрации: 28.05.2002
Какая-то странная логика. Если в таблице перемещений есть поля "откуда и куда", то в запросе нужно ДВА раза указывать справочник подразделений, а вовсе не вязать ОДИН к какой-то "комбинации из полей". В итоге получится ересь и некорректные данные. Я даже умозрительный пример не могу представить когда такая логика может быть нужна...

Если это не перемещения (несмотря на названия полей и таблиц) а просто извращённая логика проектировщика который соорудил связь "ну может по этому полю, а может по тому, а может вообще абы как" - можно сперва посочувствовать, конечно, а потом выяснить "логику" которая ожидается от запроса. Т.к. в общем случае такие схемы тоже генерят ересь и абы что в запросах, а логично работающие констрейны для них соорудить более чем проблематично.

В общем хотелось бы больше деталей...
Кстати, само по себе "использование индексов" для соединений не является самоцелью. Скажем если выбирать просто ВСЕ записи некоторой таблицы и соответствующие им элементы справочника, то индекс попросту не нужен - обе таблицы будут считаны целиком. Индекс потребуется лишь если это гигантские массивы данных, и чисто физически их записи "всем скопом" невозможно или очень затратно обработать. Для сравнительно небольших же массивов, гораздо выгоднее будет операция hash join с полным чтением обоих таблиц.
А вот если запрос оперирует подмножеством (например в твоём примере есть where где отсекается либо 90% "подразделений" и нужны движения по оставшимся, либо наоборот - 90% "движений") - ну это другое дело. Именно поэтому я не устану повторять что бессмысленно оптимизировать "куски" запроса, или то же представление в голом его виде, без учёта РЕАЛЬНЫХ запросов (всех тех дополнительных условий и ограничений которые будут использоваться в реальной работе).


------------------
WBR, Igor
Ratings: 0 negative/0 positive
Re: Oracle. Использование индексов в join
Pekpytep
Автор

Сообщений: 727
Откуда: Луганск
Дата регистрации: 19.10.2010
Согласен, логика странная, но не самая чудесатая в рамках схемы.
Суть в том, что fid_dept есть абсолютно всегда. При определенных ситуациях добавляется fid_new_dept, а спустя некоторое время в таблицу добавляется еще одна запись, в которой fid_new_dept становится fid_dept.
В общем, суть логики должна быть такова: если fid_new_dept is not null, то условие джойна - de.id_dept = mo.fid_new_dept. Если же fid_new_dept is null, то соединение по условию de.id_dept = mo.fid_dept
Короче, нужно взять только самое последнее значение, не нужно соединять по двум полям - только по одному и у fid_new_dept более высокий приоритет.
Ratings: 0 negative/0 positive
Re: Oracle. Использование индексов в join
Pekpytep
Автор

Сообщений: 727
Откуда: Луганск
Дата регистрации: 19.10.2010
Если станет понятнее, то можно было бы переписать запрос примерно так:
with moves_list as (
select
...
, de1.name as dept
, de2.name as new_dept
from moves mo
join departments de1 on mo.fid_dept = de1.id_dept
join departments de2 on mo.fid_new_dept = de2.id_dept
)
select
...
, case when new_dept is not null
then new dept else dept end as dept_name
from moves_list
where ...
Но хочется покороче и покомпактнее.
Ratings: 0 negative/0 positive
Re: Oracle. Использование индексов в join
Igor Korolyov

Сообщений: 34580
Дата регистрации: 28.05.2002
Да, значит это таки "плохой" случай с извращённой логикой... Мои соболезнования.

Но всё равно нужен весь контекст запроса. Т.к. если это тупо "выборка всего", то индекс что по отдельным полям dept/new_dept что по функции NVL от них для выполнения соединения не требуется, т.к. таблица moves будет всё одно целиком читаться - ну разве что это всё особо хитрый способ проверки ссылочной целостности, и реально в dept/new_dept есть куча значений отсутствующих в справочнике (и их чуть ли не больше чем "хороших"), так что заход со стороны справочника и доступ к moves по индексу будет оправдан.
То же соображение (приоритет "доступа" со стороны справочника - т.е. к его "минимуму" записей надо пристегнуть такой же "минимум" из moves, эффекивно отбросив бОльшую их часть) работает если есть тупо ограничивающие условия типа de.name = "asd" или такого плана.
И да, по идее тут поможет функциональный индекс. Но чтобы это увидеть потребуется РЕАЛЬНО прописать в запросе соответствующие ограничивающие условия.
Если ещё не совсем понятно, то это вариант
select ... from ... join ...
против варианта
select ... from ... join ... where de.name LIKE '%управление%'
которые зачастую могут иметь совершенно разные оптимальные планы исполнения.


Совсем другое дело констрейны - для их поддержания индексы нужны. При том если сам констрейн накручен "по выражению" (например по виртуальному полю с выражением NVL) т.е. по логике допускается что в dept будет совершенно "левое" значение, если в new_dept "правильное" которое его перебивает - тогда и индекс должен быть function based. Хотя даже при такой извращённой схеме по идее должно хватать двух тривиальных констрейнов по отдельным полям (в предположении что id гарантировано неизменны, и "старые" данные из справочника не удаляются покуда ссылка на них висит в dept_id - даже если она стала "неактуальной" в связи с вводом данных в new_dept_id).

Я, честно говоря, не встречал FK констрейнов "по выражениям", да и AK - т.е. "уникальные"/unique по выражениям не строятся (предполагаю что виртуальное поле тут как раз и поможет, но не уверен, т.к. до этого "новья" мы ещё не добрались), только сам индекс можно такой соорудить, но не констрейн...


------------------
WBR, Igor
Ratings: 0 negative/0 positive
Re: Oracle. Использование индексов в join
ВладимирС

Сообщений: 1693
Дата регистрации: 03.11.2005
Pekpytep
Если станет понятнее, то можно было бы переписать запрос примерно так:
with moves_list as (
select
...
, de1.name as dept
, de2.name as new_dept
from moves mo
join departments de1 on mo.fid_dept = de1.id_dept
join departments de2 on mo.fid_new_dept = de2.id_dept
)
select
...
, case when new_dept is not null
then new dept else dept end as dept_name
from moves_list
where ...
Но хочется покороче и покомпактнее.
И какой план у этого запроса ?
Условие WHERE надо смотреть и скорее всего индексы нужны будут по полям в нем.
Ratings: 0 negative/0 positive
Re: Oracle. Использование индексов в join
Pekpytep
Автор

Сообщений: 727
Откуда: Луганск
Дата регистрации: 19.10.2010
Такс, друзья, товарищи, господа, коллеги, праздные наблюдатели...
Похоже, я неумышленно ввел вас в заблуждение относительно условий, а вы совершенно напрасно привязались к назначению таблиц. Я не могу раскрывать названий схем, таблиц, содержимое констрейнтов и, тем более, данные, поскольку СБ не спит и я по шее получу и подвиг свой не совершу.
На самом деле обе таблицы являются логами, одна - модулей, запчастей, оборудования, одним словом - "железа", вторая - манипуляций с ними. Собственно, значение в fid_new_dept (которое таковым не является), означало бы замену одного модуля на другой. Обе таблицы объемные, выборка из обоих таблиц ограничивается дополнительными условиями (по датам и нескольким флагам). Я считал, что уровень прокачки ваших хрустальных шаров тыжпрограммиста позволит понять задачу без конкретизации всех условий. Так что я, похоже, привел неудачный пример, прошу понять и простить.

Давайте упростим поставку вопроса. Не будем привязывать к назначению, а рассмотрим ситуацию сферическую в вакууме.
Ratings: 0 negative/0 positive
Re: Oracle. Использование индексов в join
Pekpytep
Автор

Сообщений: 727
Откуда: Луганск
Дата регистрации: 19.10.2010
Теперь создаем индексы по fid_something и fid_something_new и снова смотрим план выполнения:
Ratings: 0 negative/0 positive
Re: Oracle. Использование индексов в join
Pekpytep
Автор

Сообщений: 727
Откуда: Луганск
Дата регистрации: 19.10.2010
ВладимирС
Условие WHERE надо смотреть и скорее всего индексы нужны будут по полям в нем.
Конечно же я смотрю условия WHERE и контролирую использование индексов. Но меня сейчас интересует совершенно конкретный кусочек запроса, именно условие соединения.
Ratings: 0 negative/0 positive
Re: Oracle. Использование индексов в join
Влад Колосов

Сообщений: 22664
Откуда: Ростов-на-Дону
Дата регистрации: 05.05.2005
Выражение
on de.id_dept = nvl(mo.fid_new_dept, mo.fid_dept)
не может быть оптимизировано поиском, т.к. неизвестно что придет на вход.


------------------
Совершенство - это не тогда, когда нельзя
ничего прибавить, а тогда, когда нечего убавить.
Ratings: 0 negative/0 positive
Re: Oracle. Использование индексов в join
Igor Korolyov

Сообщений: 34580
Дата регистрации: 28.05.2002
Итак начнём с самого главного.
Никогда, нет не так, НИКОГДА не суди об оптимальности разных запросов (т.е. о том какой из них быстрее, выше, сильнее ) по их cost-у. Даже если "по сути" запросы делают одно и то же. Он (cost) совершенно не для этого предназначен, и он может только вводить в заблуждение, если пытаться сравнивать по нему разные запросы. Это как сравнивать стоимость жизни в разных странах по номинальному "бюджету прожиточного минимума", но НЕ учитывать в какой валюте эта сумма посчитана.
Если уж на что и смотреть, так на параметры consistent gets, cpu usage, sorts, temp space usage в статистике собранной при реальном выполнении запроса под трассировщиком (автотрассировка сгодится).

Потом:
FTS далеко не всегда бида-печаль. Именно поэтому я и говорю что не видя полной картины (и не только сами данные, но ещё и статистика по ним, в частности clustering factor - который показывает насколько физически "упорядочены" данные в таблице относительно порядка ключей индекса) совершенно некорректно что то советовать.

Ещё:
Нельзя, т.е. бессмысленно и вредно "оптимизировать" куски запроса. Особенно в таком вот ключе "у меня там 100500 условий ограничения, мильён полей да с вызовами udf, но ты на них не смотри, ты мне заставь вот это условие работать вот этак". Заставить то можно, только обрадует ли тебя конечный результат - вот в чём вопрос
Скажем в твоих примерах:
SELECT ta.id_action - только поле id из этой таблицы вынимаешь - это позволяет вообще таблицу не читать, а брать данные из индекса (full index scan). Добавь ещё хоть одно поле из ta в запрос - в условие, или в выбираемые поля, и ситуация кардинально изменится.
ORDER BY ta.id_action - сложно понять прикладной смысл такой сортировки, но она достаточно серьёзно влияет на то как будет выполняться запрос. Если "в реале" сортировки нет, или она идёт по другому полю (пусть и из той же таблицы) то опять таки результат кардинально поменяется. Я вообще предпочитаю order в самый последний момент в запросы добавлять, и только если это реально необходимо (например клиент не может сам упорядочивать принимаемые данные, или нужен механизм "страничного" доступа) - не то чтобы серверу было "тяжело" это делать, но это таки влияет на работу оптимизатора...
Секционирование таблиц - может ОЧЕНЬ сильно влиять на то как оптимально выбирать данные из таблицы. Есть такая мощная фишка как Partition Pruning - позволяет целиком выкидывать "ненужные" для результата секции, ускоряя запрос в разы. Но там своих куча тонкостей и нюансов.
Проверять что-либо на таблице в 5 записей - тоже бессмысленно. Лучше всего на реальной таблице смотреть статистику исполнения запросов. А если и делать тест, то максимально приближенный к реальности - в т.ч. по объёмам данных и по распределению (скажем если в реальной таблице fid_something_new пусто в 90% случаев - то и в тесте надо так делать. Если в реальной таблице 1% записей справочника очень активно фигурирует во второй таблице, то и в тесте это надо учесть - такого рода "перекосы" могут вынудить вообще делать 2 варианта запросов - один для "обычных", и другой для этих "белых ворон")...

Теперь ближе к практике.
Я проверял на не самом свежем 11 сервере, и для пущей правдоподобности заполнил твои таблицы нормально (100 и 400к записей), а не 5-ю записями
Что без индексов, что с индексами - твой второй вариант примерно в 2 раза ХУЖЕ чем первый - по сути там два раза делается обработка обоих таблиц - сначала с одной половинкой OR-а, потом со второй. Да, в 12-м вероятно это уже не должно происходить, но всё же...
Добавление примитивного условия WHERE TS.ID_SOMETHING = 1234 приводит к тому что вместо полного чтения таблиц и работы HASH JOIN начинает использоваться метод соединения NESTED LOOPS и, соответственно, доступ к присоединяемой таблице по индексу.
потом я добавил к справочнику поле FLAG, и прописал в пяток записей 1-ку. Добавление условия WHERE TS.FLAG=1 тоже привело к использованию NESTED LOOPS и "индексного" доступа к tmp_action - но только после сбора статистики (включая гистограмму для нового поля) - т.к. без неё сервер ошибочно полагал что под такое условие попадёт слишком много записей, и предпочитал использовать HASH JOIN.

В общем как то так


------------------
WBR, Igor
Ratings: 0 negative/0 positive
Re: Oracle. Использование индексов в join
Igor Korolyov

Сообщений: 34580
Дата регистрации: 28.05.2002
Влад Колосов
Выражение
on de.id_dept = nvl(mo.fid_new_dept, mo.fid_dept)
не может быть оптимизировано поиском, т.к. неизвестно что придет на вход.
Нет конечно. Вполне себе может - примерно как и в фоксе - если в запросе будет "такое же условие" как и в функциональном индексе


------------------
WBR, Igor
Ratings: 0 negative/0 positive
Re: Oracle. Использование индексов в join
PaulWist

Сообщений: 14601
Дата регистрации: 01.04.2004
Заинтересовало:

Igor Korolyov
... Я вообще предпочитаю order в самый последний момент в запросы добавлять, и только если это реально необходимо (например клиент не может сам упорядочивать принимаемые данные, или нужен механизм "страничного" доступа) - не то чтобы серверу было "тяжело" это делать, но это таки влияет на работу оптимизатора...


Где хранишь условия сортировки (order by ...) и как их накладываешь на клиенте (сам механизм какой)?

PS сам тоже в некоторых местах использую такой подход, но там сортировка определена по дефолту и почти не меняется от хотелок юзера.


------------------
Есть многое на свете, друг Горацио...
Что и не снилось нашим мудрецам.
(В.Шекспир Гамлет)
Ratings: 0 negative/0 positive
Re: Oracle. Использование индексов в join
Pekpytep
Автор

Сообщений: 727
Откуда: Луганск
Дата регистрации: 19.10.2010
Дело ясное что дело темное...
Пойду-ка я покурю умных книг.
Всем спасибо, спектакль окончен.
Ratings: 0 negative/0 positive
Re: Oracle. Использование индексов в join
Igor Korolyov

Сообщений: 34580
Дата регистрации: 28.05.2002
PaulWist
Где хранишь условия сортировки (order by ...) и как их накладываешь на клиенте (сам механизм какой)?
PS сам тоже в некоторых местах использую такой подход, но там сортировка определена по дефолту и почти не меняется от хотелок юзера.
Да не храню я их нигде
Начнём с простого: Для винформс клиента, в т.ч. и для фоксовой проги сортировать "данные для отображения" можно непосредственно на клиенте - в фоксе индекс сделать на курсор, в шарпе либо тупо .OrderBy() для извлечённого списка, либо посредством BindingSource для коллекции-обёртки полноценно реализующей интерфейс IBindingList (скажем, обёртка Equin.ApplicationFramework.BindingListView), либо средства самого используемого грида (штатный DataGridView не умеет, а всякие "навороченные" - вполне) это позволяют делать с минимальными усилиями. Заодно не нужно для тривиального изменения порядка сортировки пользователем делать перезапрос источника (что IMHO есть плохое решение в 99% случаев).

Для "невизуальных" целей порядок либо не важен, либо совершенно строго фиксирован - и это тот случай когда я не против order by в запросе - ну разве что он таки реально "сводит с ума" оптимизатор, и придётся городить огород из хинтов или тупых переписываний запроса в стиле масло-масляное.

Просто ленивые/несведущие/небрежные разработчики часто ставят этот самый order by там где он ну совершенно не нужен - в представлениях (ага, а потом из этого же представления выборку делают с другим order by), или в тех же запросах но не с "бизнес-логичной" целью, а для своего личного удобства отладки - ну да, наверное для отладки неплохо видеть тот же справочник упорядоченным по id - только зачем делать такое упорядочение если "внутри" потом всё равно будет сделано ДРУГОЕ упорядочение, либо же оно для работы не нужно вовсе...
Как раз order by id и вызвал моё "непонимание" Для бизнес-целей это очень редко когда полезно, т.е. это скорее всего чисто для удобства разработчика в запросе прописано - но оно ж влияет на план, а именно план и пытаются "настраивать", и в общем "оптимизировать запрос"

2 Pekpytep
Оно да, без многократного чтения Oracle Database Performance Tuning Guide, "понимания" того о чём там пишется (а это ой как непросто в отдельных местах), и множества экспериментов/проб заниматься оптимизацией не шибко то и получится. В лучшем случае найдёшь какой-нить автоматизированный инструмент, или включишь в самом сервере автооптимизацию - но это всё весьма далеко от идеала.
Кстати, в новых версиях оптимизатор сильно поумнел - он на лету может план менять (а это очень полезно для параметризованного запроса, где параметры кардинально меняют объём обрабатываемых данных), подстраиваясь под изменившиеся данные/параметры. Но то что сложные запросы по прежнему сводят его с ума - это, увы, осталось. Боюсь что это в принципе не будет решено до тех пор пока в СУБД не встроят полноценный AI


------------------
WBR, Igor
Ratings: 0 negative/0 positive
Re: Oracle. Использование индексов в join
PaulWist

Сообщений: 14601
Дата регистрации: 01.04.2004
Igor Korolyov
PaulWist
Где хранишь условия сортировки (order by ...) и как их накладываешь на клиенте (сам механизм какой)?
PS сам тоже в некоторых местах использую такой подход, но там сортировка определена по дефолту и почти не меняется от хотелок юзера.
Да не храню я их нигде
Начнём с простого: Для винформс клиента, в т.ч. и для фоксовой проги сортировать "данные для отображения" можно непосредственно на клиенте - в фоксе индекс сделать на курсор, в шарпе либо тупо .OrderBy() для извлечённого списка, либо посредством BindingSource для коллекции-обёртки полноценно реализующей интерфейс IBindingList (скажем, обёртка Equin.ApplicationFramework.BindingListView), либо средства самого используемого грида (штатный DataGridView не умеет, а всякие "навороченные" - вполне) это позволяют делать с минимальными усилиями. Заодно не нужно для тривиального изменения порядка сортировки пользователем делать перезапрос источника (что IMHO есть плохое решение в 99% случаев).


А-а-а, понял, типа юзер имеет возможность сам упорядочить, те например, вызывается содержание накладной и оно отображается как серверу удобно, а не по порядковым номерам позиций ... тогда ясно

Igor Korolyov
Просто ленивые/несведущие/небрежные разработчики часто ставят этот самый order by там где он ну совершенно не нужен - в представлениях (ага, а потом из этого же представления выборку делают с другим order by)

Опа, не знал, что в Оракле можно создать view с order by (MSSQL такого не позволяет и это разумно)


------------------
Есть многое на свете, друг Горацио...
Что и не снилось нашим мудрецам.
(В.Шекспир Гамлет)
Ratings: 0 negative/0 positive
Re: Oracle. Использование индексов в join
Igor Korolyov

Сообщений: 34580
Дата регистрации: 28.05.2002
Не, не понял...
"Содержание строк накладной", равно как и "список накладных" в нормально спроектированной системе всегда отображаются пользователю в определённом порядке (то что пользователь его может поменять - опять же, это другой вопрос. Даже изначально они должны выводится не "абы как, как там серверу взбрело в голову их отдавать"). Кто их упорядочивает - вопрос другой.
Но если, к примеру, мы рисуем какие-то графики/диаграммы/схемы/карты, или делаем определённую программную обработку, и там по логике вполне допустимо работать с набором записей БЕЗ упорядочения, то order by теряет прикладной смысл, и остаётся исключительно в качестве "помощи разработчику при отладке". При том иногда в качестве "ложного помощника" - т.е. позволяет скрыть изъян алгоритма обработки, который проявляется если потом убрать это самое "упорядочение исходных данных".
PaulWist
не знал, что в Оракле можно создать view с order by (MSSQL такого не позволяет и это разумно)
Не знал что MSSQL "не позволяет" Оно как бы и "разумно", да на 99% "правильных" случаев найдётся же 1% исключений По хорошему оптимизатор должен эффективно выбрасывать "ненужные по логике" order by. Ну, к примеру, в запросе select f1 from (select f1 from t1 order by f2) v1 order by f1 "внутренний" order by бессмысленен, и выполнять его абсолютно точно не нужно - и да, в подавляющем большинстве случаев оптимизатор с такими задачами справляется - всё ненужное выкидывает. Но, как говорится, раз в год и палка стреляет. Лучше всё же просто не нагружать оптимизатор ненужной "интеллектуальной" работой (тем более что это не бесплатно - на "разбор" будет потрачено чуть чуть больше времени/ресурсов - а потом из таких "чуть-чуть" складываются часы впустую потраченного CPU времени и откушанной памяти).
Это, кстати, лишь один, и, наверное, самый "незначительный" нюанс в целой куче подобных "проблем". К примеру взять запрос
select f1 from (select f1, f2 from t1) v1
При правильной работе оптимизатор понимает что поле f2 "не нужно", и запросто может выбрать для доступа чисто "чтение индекса по f1" - вообще не обращаясь к самой таблице, но иногда ему не хватает ума, и он из-за этих "лишних штучек" упускает наиболее оптимальный план работы. Конечно в таком примитивном примере это очень маловероятно, но в более сложном - с теми же join-ами, где "по логике" можно вообще целые таблицы выкидывать из запросов (если констрейны гарантируют что результат от такого "выкидывания" не изменится), это уже может произойти. Кстати, это одна из причин по которой обычно советуют НЕ делать "представление из представления из представления" - т.е. использовать многоступенчатые конструкции. Хотя это и приводит в итоге к необходимости "дублировать код" (т.к. помимо "лишнего" есть же и то что "общее", из за чего и пытались использовать это представление в запросе, или другом представлении).


------------------
WBR, Igor
Ratings: 0 negative/0 positive
Re: Oracle. Использование индексов в join
PaulWist

Сообщений: 14601
Дата регистрации: 01.04.2004
Igor Korolyov
Не, не понял...
"Содержание строк накладной", равно как и "список накладных" в нормально спроектированной системе всегда отображаются пользователю в определённом порядке .

Вот я и спрашиваю где и как хранишь этот "определенный" порядок (на клиенте, на сервере, в теле кода, ... и соотвественно, какой механизм применяешь для "наложения" ордера)?

Igor Korolyov
PaulWist
не знал, что в Оракле можно создать view с order by (MSSQL такого не позволяет и это разумно)
Не знал что MSSQL "не позволяет" Оно как бы и "разумно", да на 99% "правильных" случаев найдётся же 1% исключений По хорошему оптимизатор должен эффективно выбрасывать "ненужные по логике" order by. Ну, к примеру, в запросе select f1 from (select f1 from t1 order by f2) v1 order by f1 "внутренний" order by бессмысленен, и выполнять его абсолютно точно не нужно - и да, в подавляющем большинстве случаев оптимизатор с такими задачами справляется - всё ненужное выкидывает. Но, как говорится, раз в год и палка стреляет. Лучше всё же просто не нагружать оптимизатор ненужной "интеллектуальной" работой (тем более что это не бесплатно - на "разбор" будет потрачено чуть чуть больше времени/ресурсов - а потом из таких "чуть-чуть" складываются часы впустую потраченного CPU времени и откушанной памяти).

В MSSQL используется такая последовательность:

Цитата:
А вот на вопросе сопоставления выражения и определения колонки нужно остановиться подробнее. Это делается до того как начинается основной процесс оптимизации на фазе упрощения дерева операторов. Можно назвать ее пред-оптимизацией и она состоит примерно из следующих шагов:

1. Парсинг текста запроса, построение на его основе дерева логиечских операторов привязка к объектам бд.

2. Упрощение дерева (исключение избыточных условий, противоречий, упрощение соединений, проталкивание предикатов вниз к операторам доступа и т.д.).

3. Исключение лишних соединений.

4. Нормализация проекций (в том числе сопоставление выражений вычисляемым колонкам).

5. Оптимизация.

те из select-a выкидывается всё не нужное для конечного результата, таким образом выборка
select f1 from (select f1, f2 from table) as v
"раскрывется" до таблиц, над которыми уже производится оптимизация


------------------
Есть многое на свете, друг Горацио...
Что и не снилось нашим мудрецам.
(В.Шекспир Гамлет)
Ratings: 0 negative/0 positive
Re: Oracle. Использование индексов в join
Igor Korolyov

Сообщений: 34580
Дата регистрации: 28.05.2002
PaulWist
Вот я и спрашиваю где и как хранишь этот "определенный" порядок (на клиенте, на сервере, в теле кода, ... и соотвественно, какой механизм применяешь для "наложения" ордера)?
Нет никакого "общего" места хранения.
Где-то в теле запроса, если это SQL текст. При том как на сервере (если это представление, или запрос в ХП), так и на клиенте (опять же если он использует "прямые" SQL запросы - например это фокс-программа).
Где-то в другом программном коде. Для фокса - это тривиальные index by, для шарпа - LINQ конструкции (которые в свою очередь могут работать как локально, над уже полученной коллекцией объектов, так и трансформироваться в кусок запроса order by посылаемый на сервер).
Я вообще по этому поводу не заморачиваюсь, и никакой "централизацией" что SQL-ей, что LINQ кода не занимаюсь.
Говорил я лишь о том что стоит избегать "ненужных" упорядочиваний.
PaulWist
В MSSQL используется такая последовательность:
Шаги работы оптимизатора примерно схожи во всех реализациях, речь не про них в общем то...
Речь о том что в реальных запросах как правило столько г*на понакручено, что простая/прямая логика работы оптимизатора с этим банально не справляется. Плюс к тому в реальных БД зачастую не прописано формально и половины всех тех "правил и ограничений" которые имеют место быть. Просто потому что такие "правила" не выражаются в виде AK/FK констрейна. А без "формальных правил" оптимизатор не может выкинуть вроде как "лишний" кусок работы (ну когда человек понимает что он реально лишний) - обращения к некоторым таблицам, к примеру, или вычисление некоторых ограничений (если они неявно следуют из других ограничений).

Кстати, не знаю как в mssql, а в оракле далеко не все запросы (особенно факторизованные) выполняются "чисто над исходными таблицами". Зачастую кусок запроса (промежуточный результат) "материализуется" - т.е. по сути создаётся своего рода временная таблица, и дальнейшие шаги исполнения уже с этой таблицей и работают. При том есть специальный хинт позволяющий "подсказать" оптимизатору что вот этот кусок/подзапрос следует материализовать - если он сам вдруг посчитает что этого делать не стоит.
Для некоторых типов запросов это сокращает затраты на несколько порядков.
Грубо говоря если в верхнем примере заменить таблицу tmp_action на мега-сложный подзапрос, и применить второй вариант (с OR-ами), который в 11-й версии разворачивается в два полноценных запроса "соединяемых" после отработки каждого, то получится что этот мега-сложный и затратный подзапрос придётся исполнять дважды - да, возможно "пропихивая" в него определённые условия из внешней части и там самым немного меняя результат в каждой "половинке"... Но если "пропихивать" особо нечего, или эти "ограничения" оказываются малозначительными (ну т.е. что одна что вторая половинки должны будут предоставить примерно одни и те же записи, и нужна будет реально бОльшая часть их данных), то весьма выгодно "сохранить" результат подзапроса, и потом просто дважды его пройтись для отработки "внешней" части основного запроса.
В фоксе это тоже широко используется - когда вместо мега-сложного запроса пишется "цепочка" более простых, каждый последующий из которых оперирует данными предыдущих.


------------------
WBR, Igor
Ratings: 0 negative/0 positive


Извините, только зарегистрированные пользователи могут оставлять сообщения в этом форуме.

On-line: 8 Владимир Максимов Guest (Гостей: 6)

© 2000-2024 Fox Club 
Яндекс.Метрика