Порядок выполнения условий в предложении SQL 'where'

У меня есть набор условий в моем разделе where where

WHERE 
d.attribute3 = 'abcd*'  
AND x.STATUS != 'P' 
AND x.STATUS != 'J' 
AND x.STATUS != 'X' 
AND x.STATUS != 'S' 
AND x.STATUS != 'D' 
AND CURRENT_TIMESTAMP - 1 < x.CREATION_TIMESTAMP

Какое из этих условий будет выполнено первым? Я использую оракул.

Я получу эти данные в своем плане выполнения? (У меня нет полномочий делать это в db здесь, иначе я бы попробовал)

Ответ 1

Вы уверены, что у вас нет полномочий для просмотра плана выполнения? Как использовать AUTOTRACE?

SQL> set autotrace on
SQL> select * from emp
  2  join dept on dept.deptno = emp.deptno
  3  where emp.ename like 'K%'
  4  and dept.loc like 'l%'
  5  /

no rows selected


Execution Plan
----------------------------------------------------------

----------------------------------------------------------------------------------
| Id  | Operation                    | Name         | Rows  | Bytes | Cost (%CPU)|
----------------------------------------------------------------------------------
|   0 | SELECT STATEMENT             |              |     1 |    62 |     4   (0)|
|   1 |  NESTED LOOPS                |              |     1 |    62 |     4   (0)|
|*  2 |   TABLE ACCESS FULL          | EMP          |     1 |    42 |     3   (0)|
|*  3 |   TABLE ACCESS BY INDEX ROWID| DEPT         |     1 |    20 |     1   (0)|
|*  4 |    INDEX UNIQUE SCAN         | SYS_C0042912 |     1 |       |     0   (0)|
----------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   2 - filter("EMP"."ENAME" LIKE 'K%' AND "EMP"."DEPTNO" IS NOT NULL)
   3 - filter("DEPT"."LOC" LIKE 'l%')
   4 - access("DEPT"."DEPTNO"="EMP"."DEPTNO")

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

  • условие "emp.ename как" K% "будет применено сначала, при полном сканировании EMP
  • то соответствующие DEPT записи будут выбраны с помощью индекса на dept.deptno(через метод NESTED LOOPS)
  • наконец, будет применен фильтр "dept.loc like 'l%'.

Этот порядок приложения не имеет ничего общего с тем, как предикаты упорядочиваются в предложении WHERE, как мы можем показать с помощью этого повторно заказанного запроса:

SQL> select * from emp
  2  join dept on dept.deptno = emp.deptno
  3  where dept.loc like 'l%'
  4  and emp.ename like 'K%';

no rows selected


Execution Plan
----------------------------------------------------------

----------------------------------------------------------------------------------
| Id  | Operation                    | Name         | Rows  | Bytes | Cost (%CPU)|
----------------------------------------------------------------------------------
|   0 | SELECT STATEMENT             |              |     1 |    62 |     4   (0)|
|   1 |  NESTED LOOPS                |              |     1 |    62 |     4   (0)|
|*  2 |   TABLE ACCESS FULL          | EMP          |     1 |    42 |     3   (0)|
|*  3 |   TABLE ACCESS BY INDEX ROWID| DEPT         |     1 |    20 |     1   (0)|
|*  4 |    INDEX UNIQUE SCAN         | SYS_C0042912 |     1 |       |     0   (0)|
----------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   2 - filter("EMP"."ENAME" LIKE 'K%' AND "EMP"."DEPTNO" IS NOT NULL)
   3 - filter("DEPT"."LOC" LIKE 'l%')
   4 - access("DEPT"."DEPTNO"="EMP"."DEPTNO")

Ответ 2

В базе данных будет определен порядок выполнения условий.

Обычно (но не всегда) он будет использовать индекс, где это возможно.

Ответ 3

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

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

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

WITH subset AS
  ( SELECT /*+ materialize */
      FROM my_table
      WHERE CURRENT_TIMESTAMP - 1 < x.CREATION_TIMESTAMP
  )
SELECT *
  FROM subset
  WHERE 
  d.attribute3 = 'abcd*'  
  AND x.STATUS != 'P' 
  AND x.STATUS != 'J' 
  AND x.STATUS != 'X' 
  AND x.STATUS != 'S' 
  AND x.STATUS != 'D'

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

Я не советую вам делать это как общую привычку. В большинстве случаев простое письмо простого запроса приведет к лучшим планам выполнения.

Ответ 4

Чтобы добавить к другим комментариям планы выполнения, в рамках модели калькуляции на основе процессора, введенной в 9i и используемой по умолчанию в 10g + Oracle, также будет проведена оценка того, какой порядок оценки предикатов приведет к снижению вычислительной стоимости, даже если это произойдет не влияют на порядок доступа и метод доступа к таблице. Если выполнение одного предиката перед другим приводит к меньшему количеству выполняемых вычислений предикатов, то этот оптимизатор может быть применен.

См. эту статью для более подробной информации: http://www.oracle.com/technology/pub/articles/lewis_cbo.html

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

Сложный материал.

Ответ 5

Наконец, теория реляционных баз данных говорит, что вы можете никогда зависеть от порядка выполнения предложений, поэтому лучше не пытаться. Как говорили другие, оптимизатор с затратами пытается выбрать то, что, по его мнению, является лучшим, но даже просмотр плана объяснений не гарантирует фактический порядок, который использовался. Объяснение плана просто говорит вам, что рекомендует CBO, но это еще не 100%.

Может быть, если вы объясните, почему вы пытаетесь это сделать, некоторые могут предложить план?

Ответ 6

Трудный вопрос. Просто столкнулся с той же дилеммой. Мне нужно указать функцию внутри запроса. Сама функция выполняет другой запрос, поэтому вы понимаете, как это влияет на производительность в целом. Но в большинстве случаев мы имеем функцию, которая не будет вызываться так часто, если остальные условия выполняются в первую очередь.

Ну, подумал, что было бы полезно опубликовать здесь еще одну статью для темы.

Следующая цитата скопирована с сайта Дональда Бурлесона (http://www.dba-oracle.com/t_where_clause.htm).

Подсказка ordered_predicates указана в предложении Oracle WHERE запрос и используется для указания порядка, в котором булевы предикаты следует оценить.

В отсутствии order_predicates, Oracle использует следующие шаги для оценки порядка предикатов SQL:

  • Подзапросы оцениваются перед внешними булевыми условиями в предложении WHERE.

  • Все булевы условия без встроенных функций или подзапросов оцениваются в обратном порядке от порядка, в котором они находятся в ГДЕ, с первым оценкой последнего предиката.

  • Булевы предикаты со встроенными функциями каждого предиката оцениваются в порядке возрастания оценочных затрат.