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

 

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

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

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


AND ...

В этом примере база данных может обратиться к Order_Detai I s при помощи индекса по Order_ID, если параметр : 1 не равен nul 1. Ho если параметр . 1 все же принимает значение null, то никаких ограничений для Order_ID не остается и индекс не используется. Так как во время разбора SQL и подготовки плана база данных не может предсказать, какое именно значение будет у параметра : 1, она не увидит никакой подходящей возможности использовать индекс. В этом случае хорошим решением будет создание плана из двух частей, где каждая часть будет оптимизирована для одного из возможных случаев:

SELECT ...

FROM OrderJDetails D.

WHERE ...

AND D.DrderJD=:I AND :1 IS NOT NULL AND ...

UNION ALL SELECT ...

FRDM OrderJDetails D.

WHERE ..

AND :1 IS NULL AND ...

Когда вы просматриваете план выполнения для этого запроса, вы видите, что используется индексированный доступ при помощи индекса по Order_Detai I s(0rder_ID) и доступ с полным сканированием таблицы к OrderJMai I s. Это может показаться наихудшим решением, но вы защищены дополнительными условиями.

AND : I IS NOT NULL

AND :1 IS NULL

В этих условиях нет никакого обращения к данным базы, поэтому она оценивает условия перед тем, как начинает считывать данные для этой половины комби-
Универсальные техники управления планами

99

нированного оператора. Таким образом, на самом деле она никогда не выполняет полное сканирование таблицы, если значение параметра : 1 не равно null, и никогда не выполняет индексированное считывание (и любую другую часть плана выполнения для первой половины запроса), если значение параметра : 1 равно nul 1. Так описывается метод разветвления плана выполнения в зависимости от условий по параметрам, которые определяют, какие данные будут использоваться для выполнения запроса. Единственная хитрость: вы должны убедиться, что условия по связанным переменным взаимно исключают друга, чтобы данные возвращались только из одной ветви плана выполнения. Например, если у вас есть другой параметр для определения Customer_Name, вы можете собрать запрос так:

SELECT ...

FROM Order_Details D. Customers С. ...

WHERE ...

AND D.Order_ID=:1 AND : I IS NDT NULL

AND (C.Customer_Name=:2 DR :2 IS NULL)

AND ..

UNIDN ALL SELECT ...

FROM Order DetaiIs D. Customers C. .

WHERE ...

AND :1 IS NULL AND :2 IS NOT NULL AND C.Customer_Name=:2 AND ...

UNION ALL SELECT ...

FROM Order DetaiIs D. Customers C.

WHERE ...

AND :1 IS NULL AND :2 IS NULL AND ...

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

1. Обращается к таблице Orders через индекс по 0rder_ID (первый вариант), когда это возможно.

2. В ином случае обращается к таблице Customers при помощи индекса по полю Customer_Name (второй вариант), если 0rder_ID не указан, но указано имя покупателя.

3. Если оба предыдущих варианта не подходят, сервер просто получает все строки — вероятно, начиная с полного сканирования таблицы, если нет никаких селективных условий.

В любом случае условия для связанных переменных во всех трех частях являются взаимоисключающими:

AND :1 IS NOT NULL
AND : 1 IS NULL
AND :2 IS NOT NULL
AND :1 IS NULL
AND :2 IS NULL
100

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

Запрещение использования неправильных индексов

Выражения для соединений обычно просты и выполняются на совместимых типах, например числовых идентификаторах. Условия для основной таблицы в данном случае также достаточно просты и позволяют использовать индекс. Более распространенная задача, чем принудительное использование правильного индекса при обработке запроса, — это запрещение использования неправильного индекса. Во многих запросах присутствует множество однотабличных условий, которые разрешают использовать различные индексы, но вы хотите применить единственный из них, который позволит выполнить запрос максимально быстро. Условия соединения обычно выражены так, чтобы разрешить соединения с использованием индекса в обоих направлениях, хотя лишь одно из возможных направлений соединения оказывается оптимальным. Иногда лучше полностью запретить использовать индекс при соединении, чтобы реализовать соединение хэшированием или сортировкой слиянием.

Чтобы запретить использование индекса, создайте простейшее из возможных выражений при упоминании индексированного столбца. Например, вам нужно предотвратить использование индекса по Status_Code для недостаточно селективного условия по закрытым заказам, так как с течением времени количество закрытых заказов будет все существенней превышать количество открытых заказов:

O.Status_Code='CL'

Так как Status_Code — это столбец символьного типа, простейшим выражением, запрещающим использование индекса без изменения результатов, будет простое присоединение пустой строки к концу Status_Code.

В Oracle и DB2 мы можем использовать выражение O.Status_Code| |''=' CL'

В SQL Server будет применяться выражение 0. Status_Code+ "=' CL'

Для столбцов числового типа можно прибавить 0, получив следующее условие:
Предыдущая << 1 .. 43 44 45 46 47 48 < 49 > 50 51 52 53 54 55 .. 161 >> Следующая
Реклама
Авторские права © 2009 AdsNet. Все права защищены.
Rambler's Top100