|
Программирование >> Полное сканирование таблицы
мание, что даже если вы измените запрос или модель данных, чтобы добиться полной селективности в условиях диапазона индекса, стоимость снизится лишь минимально. Ненужными окажутся большинство из 43 операций считывания хорошо кэшированных листовых блоков индекса, что ускорит запрос приблизительно на миллисекунду. Никакого эффекта на 155 более дорогих операций считывания блоков таблицы не будет. Можно изменить приложение, чтобы выполнялось чувствительное к регистру сравнение имен, и создать новый индекс, В1слючающий только эти два столбца. Или же можно изменить таблицу, хранить имена в верхнем регистре и индексировать этот новый столбец вместе со столбцом кода области. Таким образом, хотя этот запрос и индекс не идеально подходят друг другу, индекс вполне можно использовать. Добавление нового индекса и изменение запроса для получения небольшого потенциального преимущества во времени не стоят усилий. Комбинирование индексов Случается, что база данных находит фильтры с условиями равенства, которые указывают на различные одностолбцовые индексы. Объединив операции сканирования диапазонов этих индексов, база данных может получить селективность многостолбцового фильтра еще до того, как начнет обращение к таблице. Давайте еще раз воспользуемся предыдущим примером запроса, который указывает код области и имя покупателя, но заменим многостолбцовый индекс одностолбцовыми индексами по двум нужным нам столбцам. Далее заменим условие UPPERCFi rst Name) на простое соответствие по столбцу, предполагая, что все значения хранятся в верхнем регистре. Типичные условия выглядят следующим образом: WHERE Агеа Ссс1е=415 AND Fi rst Name=BRUCE: Теперь можно предположить, что в листовом блоке находится обычное количество строк - 300 или более, так как одностолбцовые индексы созданы по коротким столбцам. Используя те же значения селективности фильтров по одному столбцу и предполагая, что в таблице содержится 1 ООО ООО строк, можно предсказать, что условие для Агеа Сос1е даст 8 600 (0,0086 х 1 ООО ООО) строк, для чего потребуется использовать 29 (8 600/300) листовых блоков индекса. Второе сканирование диапазона индекса, для удовлетворения условия для FirstName, даст 18 000 (0,018 X 1 ООО ООО) строк, что требует использования 60 (18 000/300) листовых блоков индекса. Так как оба условия являются условиями равенства, база данных находит два уже отсортированных списка идентификаторов строк и может легко объединить их, отыскав те же 155 идентификаторов строк таблицы, как и в случае с многостолбцовым индексом. Описанная здесь операция, слияние списков идентификаторов строк, полученных из двух индексов, называется операцией AND-EQUAL MERGE для индекса (слияние по условиям равенства и условию И), и база данных может выполнять эту операцию с любым количеством условий равенства для одностолбцовых индексов. Стоимость доступа к таблице такая же, как при поиске строк по многостолбцовому индексу, но считать необходимо больше листовых блоков индекса - в данном случае 89 (29 + 60) вместо 43 в предыдущем примере. Как вы можете видеть, стоимость операции AND-EQUAL MERGE больше, чем применения многостолбцового индекса, но этот вариант может быть лучше, чем использование единственного одностолбцового индекса. Но такой случай, то есть разумное предпочтение операции AND-EQUAL MERGE, очень редок. Практически всегда наиболее селективное условие по одному столбцу само по себе является прекрасным вариантом, и стоимость менее селективного сканирования диапазона индекса превышает экономию на доступе к таблице, либо добавленная стоимость операции AND-EQU AL MERGE оправдывает создание многостолбцового индекса. Если вы замечаете в плане выполнения операцию AND-EQUAL MERGE, практически всегда следует либо запретить использование менее селективного индекса, либо создать и использовать многостолбцовый индекс. Новый многостолбцовый индекс должен начинаться с наиболее селективного столбца, в нашем случае это будет поле AreaCode, и чаще всего должен использоваться вместо любого одностолб1Ювого индекса по этому столбцу. Соединения Однотабличные запросы быстро перестают казаться интересной задачей настройки. Возможных вариантов достаточно мало, что позволяет использовать даже метод проб и ошибок, который достаточно быстро приведет к появлению наилучшего плана выполнения. Многотабличные запросы намного интереснее. Чтобы настраивать многотабличные запросы, вам необходимо понимать различные типы соединений и преимущества и недостатки разнообразных способов выполнения соединения. Типы соединений Начнем с того, что попытаемся четко понять, что же означает многотабличный запрос. Сначала рассмотрим, как базы данных понимают соединения - операции, которые комбинируют строки из нескольких таблиц для получения требуемого результата. Начнем с простейшего многотабличного запроса: SELECT ... FROM Orders. Orderjetails; Если фразы WHERE нет, то у базы данных также нет инструкций, как нужно скомбинировать строки из этих двух больших таблиц, и она делает простейшую вещь: возвращает все возможные комбинации строк из таблиц. Если у вас есть 1 ООО ООО заказов и 5 ООО ООО описаний заказов, то запрос вернет (если вы сможете дождаться) 5 ООО ООО ООО ООО строк! Это редко используемое и еще реже необходимое декартово соединение. Результат этого запроса - все возможные комбинации элементов из двух или более наборов - называется декартовым произведением. С точки зрения ведения бизнеса вам совершенно неинтересно комбинировать данные из заказов и описаний заказов, если они не имеют никакого отношения друг к другу. Если вы увидели в программе декартово соединение, практически всегда это ошибка. ПРИМЕЧАНИЕ- Самое распространенное, но все так же очень редкое исключение из этого правила - это спуцш, когда одна из таблиц возвращает единственную строку. В этом случае запрос на декартово соединение можно рассматривать как бо.- ее или менее разумную комбинацию результатов, полученных из запроса к одной строке и присос; пненных для удобства к результатам логически независимого многострочного запроса. Внутренние соединения Любому приложению обработки заказов обязательно понадобятся подробности, относящиеся к определенным заказам, поэтому вы вряд ли увидите декартово соединение. Скорее условие соединения будет указывать базе данных, в каких отношениях находятся таблицы: SELECT ... FROM Orders 0. Order Details D WHERE O.Order ID-D.Order IO; Или, если записать в новом стиле: SELECT ... FROM Orders О INNER JOIN Grder Detans 0 ON 0.0rder ID=D.Order I0: Логически такую операцию можно считать декартовым произведением с фильтрованным результатом: выдать все комбинации заказов и описаний, но удалить те комбинации, для которых идентификаторы заказов не совпадают . Такое соединение называется внутренним соединением. Даже в худших случаях базы данных практически всегда находят лучший способ поиска требуемых строк, чем метод решения в лоб , когда сначала вычисляется декартово произведение, а потом из него удаляются составляющие, не отвечающие условиям запроса. И это замечательно, так как для получения многостороннего декартова произведения нескольких больших таблиц может потребоваться несколько лет, а то и вечность. Большинство соединений, например приведенное в примере, содержат условие равенства внешнего ключа в какой-то подчиненной таблице и первичного (уникального) ключа в главной таблице, но любое условие, в котором упоминают две или (реже) больше таблиц, является условием соединения. С процедурной точки зрения у базы данных есть несколько способов соединить таблицы в указанных запросах наилучшим образом. Начать с главной таблицы и найти все гоответствующие подчиненные данные, ш Начать с детальной таблицы и найти соответствуюшие главные строки. Получить оба набора строк независимо (но не при помощи декартова произведения) и каким-либо образом соединить их, соблюдая соответствие между значениями соединенных столбцов. Хотя результаты во всех случаях будут одинаковыми, производительность этих способов может радикально различаться, поэтому в этой книге будет подробно описан выбор наилучшего варианта. Внешние соединения Распространенная альтернатива внутреннему соединению - внешнее соединение. Проще всего описать внешнее соединение в терминах выполнения. Для его получения следует начать со строк основной таблицы и найти, где это возможно, подходящие строки из второй таблицы внешнего соединения. Если база данных не может найти подходящую строку, требуется создать искусственную запись, состоящую из значений null, и присоединить ее к строке из ведущей таблицы. Например, рассмотрим запрос Oracle в старом стиле: SELECT D.Department Name FROM Employees E. Departments D WHERE E.Oepartment ID=D.Department ID(+); В новом стиле записи в любой базе данных запрос будет выглядеть так: SELECT .... D.DepartmentJame FROM Employees E
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |