|
Программирование >> Полное сканирование таблицы
Employee Hire Date по столбцу Hire Date удачно решают эту проблему, возвращая нужную строку при помощи всего лишь одной операции логического ввода-вывода для таблицы: SELECT /*+ INDEX DESC(E Employee Hire Date) */ * FROM Employees E WHERE Hire Date>=TO DATE(2003-04-01.YYYY-MM-DD) AND Hire Date< TC DATEC2003-05-0r.YYYY-MM-DD) AND R0WNUM=1 Обратите внимание, что я удалил явное упоминание ORDER BY, так как он создает ложное впечатление эффективности, и добавил условие для ROWNUM. ВНИМАНИЕ - Предыдуишй пример может произвести впечатление рискованного кода, который может разрушить функциональность, например, если кто-либо удалит или переименует используемый код. Это действительно рискованно, и я рекомендую использовать такой подход, только если улучшение производительности существенно превышает стоимость риска получения неправильных результатов. Такой случай характерен для синтаксиса SQL, разрешающего подобные запросы, возвращающие первые несколько записей из набора, которые в полной мере используют преимущества наилучшего индексированного пути. Используя текущий синтаксис, я еще не нашел решения, которое являлось бы одновременно оптимальным и функционально безопасным. Существует несколько других подсказок для доступа к таблицам, которые я не привел в этом разделе, но я никогда не сталкивался со случаями, когда они были бы полезны. Подсказки для порядка выполнения запроса Далее перечислены основные подсказки для управления порядком вьшолнения соединений и подзапросов. ORDERED. Рекомендует Oracle, когда возможно, соединять таблицы в том порядке, в каком они перечислены во фразе FROM. ПРИМЕЧАНИЕ Эта подсказка, в отличие от остальных, обычно требует изменения тела SQL-запроса (или, по крайней мере, раздела FROM) для получения желаемого плана, так как она относится к порядку выполнения FROM. Обратите внимание, что желаемый порядок перечисления таблиц в разделе FROM будет в точности противоположным наилучшему порядку раздела FROM, который вы бы выбрали для синтаксической оптимизации. Это происходит потому, что RBO работает справа налево, в то время как подсказка заставляет СВО выполнять FROM слева направо. 1ЕМ)Ш(.<Имя псевдонина>). Если подсказка ORDERED не указана, то выбирается ведущая таблица, то есть первая таблица в порядке соединения. Хотя в данном случае вы в меньшей степени контролируете порядок вьшолнения, чем с подсказкой ORDERED, вам зато не требуется изменять раздел FROM. Часто один лишь выбор правильной ведущей таблицы - это все, что требуется для получения производительности, близкой к оптимальной. Последующий порядок соединения значит меньше и, вероятнее всего, будет удачно выбран оптимизатором без вашей помощи. PUSH SUBQ. Эта подсказка приказывает оптимизатору выполнять коррелированные подзапросы, как только это возможно - как только внешний запрос достигнет столбцов соединения, необходимых для оценки подзапросов. Обычно СВО в Oracle выполняет коррелированные подзапросы только после завершения всех соединений во внешнем запросе. Подсказки ORDERED и LEADING часто встречаются и их легко использовать. Иногда бьшает полезной подсказка PUSH SUBQ. Когда дело доходит до подзапросов, Oracle предлагает управление на основе подсказок только для двух крайних случаев - выполнение подзапросов как можно раньше и как можно позже. Однако вы сможете полностью контролировать момент вьшолнения подзапросов, если примените подсказку PUSH SUBQ вместе с методами, позволяющими откладывать коррелированные соединения, описанными ранее. Например, рассмотрим запрос: SELECT ... FROM Orders 0. Customers С, Regions R WHERE O.Status Code=OP AND O.Customer ID=C.Customer ID AND C.Customer Type Code=GOV AND C.Region ID=R.Region ID AND EXISTS (SELECT NULL FROM Order Details OD WHERE 0. Drder I D+0*C. Custorner ID=OD. Order ID AND 0D.Shipped F1ag=Y) Без подсказки Oracle выполняет проверку EXISTS после соединения всех трех таблиц во внешнем запросе. Смысл выражения O.Order ID+0*C.Customer ID заключается в том, чтобы отложить проверку EXISTS и вьшолнить ее только после присоединения С, но перед присоединением R. В случае, когда нет никаких подсказок, все условия EXISTS автоматически откладываются, пока не будут выполнены все соединения во внешнем запросе. Чтобы заставить условие EXISTS выполняться между присоединением С и R, используйте и подсказку, и выражение, позволяющее отложить коррелированное соединение: SELECT /*+ PUSH SUBQ */ ... FROM Orders 0. Customers С, Regions R WHERE O.Status Code=DP AND O.Customer ID=C.Customer ID AND C.Customer Type Code=GOV AND C.Region ID=R.Region ID AND EXISTS (SELECT NULL FROM Order Details OD WHERE 0.Order ID+0*C.Customer ID=OD.Order ID AND DD.Shipped Flag=V) Теперь подсказка PUSH SUBQ заставляет Oracle выполнять условие EXISTS как можно раньше, а выражение O.Order ID+0*C.Customer ID гарантирует, что этот момент не наступит, пока не будет выполнено соединение с С. Подсказки для методов соединения Далее перечислены основные подсказки для управления методами соединения. USE NL (<Список псевдонимов>). Рекомендует Oracle соединять таблицы, перечисленные в списке псевдонимов, используя вложенные циклы. Псевдонимы в списке не должны разделяться запятыми, например, USE NL(T1 Т2 ТЗ). USE HASH (<писок псевдонимов>). Предлагает серверу соединять таблицы, перечисленные в списке псевдонимов, используя хэширование. Псевдонимы в списке не должны разделяться запятыми, например USE HASH(T1 Т2 ТЗ). Пример Приведу пример подсказок, при помощи которых можно добиться полного контроля над планом вьшолнения. Я принудительно выберу порядок соединения, метод доступа к каждой таблице и метод соединения для каждой таблицы. Рассмотрим ранее встречавшийся нам пример, настроенный для RBO и показанный в конце раздела Управление синтаксическими планами вьшолнения в Огас1е?>. Чтобы полностью контролировать план вьшолнения и при этом заменить первое соединение со вложенными циклами на соединение хэшированием, а местоположение сотрудников считывать через индекс по Description, используйте такой запрос: SELECT /*+ ORDERED USE NL(M LM) USE HASH(LE) INDEXCE Emp1oyee Last Name) INDEX(LE Location Description) INDEX(M Employee Pkey) INDEX(LM Locati onPkey) */ E.F1rst Name. E.Last Name, E.Salary, LE,Description. M.First Name. M.Last Name, LM.Description FROM Employees E. Locations LE, Employees M. Locations LM WHERE E.Last Name = Johnson AND E.Manager ID = M.Employee ID AND E.Location ID = LE.Location ID AND M.LocationJD = LM.LocationJD AND LE.Description = Dallas Будет получен следующий план выполнения: SQL> еех PLAN SELECT STATEMENT NESTED LOOPS NESTED LOOPS HASH JOIN TABLE ACCESS BY INDEX ROWID 1*EMPL0YEES INDEX RANGE SCAN EMPLOYEE LAST NAME TABLE ACCESS BY INDEX ROWID 2*LDCATIDNS INDEX RANGE SCAN LOCATION DESCRIPTION TABLE ACCESS BY INDEX ROWID 3*EMPLDYEES INDEX UNIQUE SCAN EMPLOYEE PKEY TABLE ACCESS BY INDEX ROWID 4*L0CATI0NS INDEX UNIQUE SCAN LOCATION PKEY Управление планами в DB2 DB2 предлагает лишь несколько собственных инструментов управления планами вьтолнения, поэтому для настройки в DB2 применяются косвенные методы. Настройка в DB2 выполняется за три основных шага. 1. Предоставить оптимизатору хорошую статистику по таблицам и индексам, чтобы он мог точно подсчитать стоимость различных вариантов. 2. Выбрать уровень оптимизации, который DB2 будет применять к запросу. 3. Изменить запрос, чтобы запретить нежелательные планы вьшолнения, используя, в основном, методы, описанные ранее в разделе Универсальные техники управления планами .
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |