Информационный сайт

 

Реклама
bulletinsite.net -> Книги на сайте -> Программисту -> Тоу Д. -> "Настройка SQL. Для профессионалов" -> 50

Настройка SQL. Для профессионалов - Тоу Д.

Тоу Д. Настройка SQL. Для профессионалов — СПб.: Питер, 2004. — 333 c.
ISBN 5-94723-959-0
Скачать (прямая ссылка): nastroykasqldlyaprof2004.djvu
Предыдущая << 1 .. 44 45 46 47 48 49 < 50 > 51 52 53 54 55 56 .. 161 >> Следующая


0.Region_ID+0=137

Во всех базах данных есть функции определенного вида, значение которых приравнивается к первому аргументу, если он не равен nul 1, а в противном случае — ко второму аргументу. В Oracle это функция NVLO. В SQL Server и DB2 это COALESCEC). Если оба аргумента выражения оперируют данными одного и того же поля, функция всегда возвращает один и тот же результат в виде самого столбца, независимо от его типа. Таким образом, мы получаем простой способ отключения использования индекса независимо от типа столбца.

Для Oracle зто будет выражение: NVL(0.OrderJDate.0.OrderJDate) = <3начение>

В DB2 и SQL Server для достижения той же цели придется использовать выражение: COALESCE (0. OrderJDate. 0. OrderJDate)=<3rave/we>

Условие для соединения, запрещающее индексированный доступ к 0. Regi on_ID (но не к R. Regi on_ID) может выглядеть следующим образом:

О.Regi on_ID+0=R.Regi on_ID

Используя универсальный подход, то же соединение можно записать так:

NVL(0.Regi on_ID.О.Regi on_ID)=R.Regi on_ID
Универсальные техники управления планами

101

Использование желаемого порядка соединения

Кроме непредумышленного запрещения использования индексов, есть еще два случая, когда бывает невозможно провести соединение в нужном порядке.

¦ Использование внешних соединений.

¦ Отсутствие избыточных условий соединения.

Внешние соединения

Рассмотрим запрос с внешним соединением в записи Oracle:

SELECT ...

FROM Employees E. Locations L WHERE E,Location_ID=L.Location_I0(+)

или в новом варианте записи операторов:

SELECT ...

FROM Employees E LEFT OUTER JOIN Locations L ON E.Location_ID=L.Location_ID

Этот запрос получает записи сотрудников и соответствующие им записи об их местоположении. Если для сотрудника не указано местоположение, то используется значение nul 1. Основываясь на этом запросе, легко понять, что он не может эффективно работать, начиная с таблицы Locations и переходя к Employees, так как требуются даже те сотрудники, для которых местоположение не указано. Представьте случай, когда этот запрос является лишь шаблоном, к которому приложение добавляет условия, зависящие от критерия поиска, заданного конечным пользователем. Если пользователю требуются сотрудники с определенным местоположением, приложение может создать такой запрос:

SELECT ...

FROM Employees E LEFT OUTER JOIN Locations L DN E.Location_ID=L.Location_ID WHERE L.Description='Headquarters1

В случае внешнего соединения в порядке от Employees к Locations полю L.Description будет присвоено значение null и условие для L.Description будет ложным. Только внутреннее соединение вернет строки, которые отвечают ограничениям для L. Descri pti on, поэтому имеет смысл изменить порядок соединения на противоположный, от Locations к Employees. Однако существование внешнего соединения часто не позволяет автоматическому оптимизатору выбрать обратный порядок для внешнего соединения, поэтому это соединение необходимо явно сделать внутренним, чтобы добиться нужного порядка:

SELECT ...

FRDM Employees E INNER JOIN Locations L

ON E.Location_ID=L.Location_ID WHERE L.Description='Headquarters'

Отсутствие избыточных условий соединения

Обычно в SQL-запросе между любым количеством таблиц количество соединений на единицу меньше количества таблиц. Например, между тремя таблицами вы ожидаете увидеть два соединения. Иногда запрос позволяет использовать дополнительное, избыточное соединение. Например, если у вас есть таблица Addresses, в которой хранятся все адреса, важные для компании, то между ней и таблицей Locations может существовать отношение вида «один к нулю» или «один к одно-
102

4. Управление планами выполнения

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

SELECT ...

FROM Employees Е. Locations L. Addresses A WHERE E.Locati on_ID=L.Locati on_ID AND E.Location_ID=A.Address_ID AND A.ZIP_Code=95628

По свойству транзитивности (если a=b и b=c, то а=с) условие L.Location_ID=A. Address_ID должно быть истинным для всех строк, которые вернет запрос. Однако это условие не указано в запросе явно, и не все базы данных смогут вывести его и подставить в запрос. В этом случае лучшим планом будет взять все адреса с данным почтовым индексом и сразу же соединить их с Locati ons, чтобы отбросить все адреса кроме одного или двух, соответствующих адресам компании, а затем соединить с Employees. Так как этот порядок соединения требует отсутствующего условия соединения, позволяющего использовать индексированный путь от Addresses к Locations, необходимо явно указать отсутствующее условие соединения:

FROM Employees Е. Locations L. Addresses А WHERE E.Location_ID=L.Locati on_ID AND E.Location_ID=A.Address_ID AND L.Location_ID=A.Address_ID AND A.ZIP_Code=95628

Так как вы не хотите использовать соединение от Addresses к Employees напрямую, можно также удалить, если необходимо, избыточное условие соединения Е.Location_ID=A.Address_ID, запретив нежелательную операцию соединения.
Предыдущая << 1 .. 44 45 46 47 48 49 < 50 > 51 52 53 54 55 56 .. 161 >> Следующая
Реклама
Авторские права © 2009 AdsNet. Все права защищены.
Rambler's Top100