16

我的 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

这些条件中的哪一个将首先执行?我正在使用甲骨文。

我会在我的执行计划中获得这些详细信息吗?(我无权在此处的数据库中执行此操作,否则我会尝试)

4

6 回答 6

22

确定您“无权”查看执行计划吗?使用 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 上的索引选择匹配的 DEPT 记录(通过 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")
于 2008-12-04T11:40:46.533 回答
7

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

通常(但并非总是)它会在可能的情况下首先使用索引。

于 2008-12-04T10:28:53.107 回答
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”提示应该使优化器首先执行内联查询,然后扫描该结果集以查找其他条件。

我不建议您将此作为一般习惯。在大多数情况下,只需编写简单的查询即可获得最佳执行计划。

于 2008-12-04T15:13:28.147 回答
1

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

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

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

复杂的东西。

于 2008-12-04T15:39:47.550 回答
1

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

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

于 2009-01-02T19:40:46.813 回答
-1

棘手的问题。刚刚面临同样的困境。我需要在查询中提及一个函数。该函数本身会进行另一个查询,因此您了解它通常如何影响性能。但是在大多数情况下,如果其余条件先执行,则不会经常调用该函数。

Well, thought it would be useful to post here another article for topic.

The following quote is copied from Donald Burleson's site (http://www.dba-oracle.com/t_where_clause.htm) .

The ordered_predicates hint is specified in the Oracle WHERE clause of a query and is used to specify the order in which Boolean predicates should be evaluated.

In the absence of ordered_predicates, Oracle uses the following steps to evaluate the order of SQL predicates:

  • Subqueries are evaluated before the outer Boolean conditions in the WHERE clause.

  • All Boolean conditions without built-in functions or subqueries are evaluated in reverse from the order they are found in the WHERE clause, with the last predicate being evaluated first.

  • Boolean predicates with built-in functions of each predicate are evaluated in increasing order of their estimated evaluation costs.

于 2015-09-24T14:52:41.700 回答