SQL'where'子句中条件的执行顺序

时间:2008-12-04 10:26:11

标签: sql oracle 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

首先执行以下哪些条件?我正在使用oracle。

我是否会在执行计划中获得这些详细信息? (我没有权限在数据库中这样做,否则我会尝试)

6 个答案:

答案 0 :(得分:19)

肯定你“没有权力”看到执行计划?怎么用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 like'K%'”将首先应用于EMP的全面扫描
  • 然后将通过dept.deptno上的索引(通过NESTED LOOPS方法)选择匹配的DEPT记录
  • 最后将应用过滤器“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")

答案 1 :(得分:7)

数据库将决定执行条件的顺序。

通常(但不总是)它会尽可能先使用索引。

答案 2 :(得分:6)

如前所述,查看执行计划将为您提供一些信息。但是,除非您使用计划稳定性功能,否则您不能依赖执行计划始终保持不变。

对于您发布的查询,看起来评估顺序不会以任何方式改变逻辑,所以我猜您正在考虑的是效率。 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'

“materialize”提示应该使优化器首先执行内联查询,然后针对其他条件扫描该结果集。

我不是建议你这样做是一般习惯。在大多数情况下,只需编写简单查询即可获得最佳执行计划。

答案 3 :(得分:1)

要添加到执行计划的其他注释,在9i中引入的基于cpu的成本计算模型,默认情况下在10g + Oracle中使用,还将评估哪个谓词评估顺序将导致较低的计算成本,即使这样做不影响表访问顺序和方法。如果在另一个谓词之前执行一个谓词导致执行的谓词计算更少,则可以应用该优化。

有关详细信息,请参阅此文章:http://www.oracle.com/technology/pub/articles/lewis_cbo.html

此外,Oracle甚至不必执行谓词,其中与检查约束或分区定义的比较表明无论如何都不会返回任何行。

复杂的东西。

答案 4 :(得分:1)

最后,关系数据库理论说你可以从不依赖于查询子句的执行顺序,所以最好不要尝试。正如其他人所说,基于成本的优化器试图选择它认为最好的,但即使查看解释计划也不会保证使用的实际订单。解释计划只是告诉你CBO推荐的内容,但这仍然不是100%。

也许如果你解释为什么要这样做,有些人可能会建议一个计划?

答案 5 :(得分:-1)

棘手的问题。刚刚面临同样的困境。我需要在查询中提到一个函数。函数本身会生成另一个查询,因此您可以了解它如何影响性能。但是在大多数情况下,如果其余的条件首先执行,那么函数就不会被调用。

嗯,认为在这里发表另一篇主题文章会很有用。

以下引用来自 Donald Burleson 的网站(http://www.dba-oracle.com/t_where_clause.htm)。

  

ordered_predicates 提示在Oracle WHERE子句中指定   查询,用于指定布尔谓词的顺序   应该进行评估。

     

缺少ordered_predicates 时,Oracle使用   以下步骤来评估SQL谓词的顺序:

     
      
  • 在WHERE子句中的外部布尔条件之前计算子查询。

  •   
  • 所有没有内置函数或子查询的布尔条件都按照它们在WHERE中找到的顺序进行反向计算   子句,首先评估最后一个谓词。

  •   
  • 具有每个谓词的内置函数的布尔谓词将按其估计的评估成本的递增顺序进行评估。

  •   
相关问题