用于执行查询的Oracle优化器

时间:2013-05-18 07:54:04

标签: sql oracle sql-execution-plan

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
Plan hash value: 2822030489
---------------------------------------------------------------------------------------------

| Id  | Operation                   | Name          | Rows  | Bytes | Cost (%CPU)| Time     |
---------------------------------------------------------------------------------------------
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |               |     1 |    46 |     2   (0)| 00:00:01 |
|   1 |  TABLE ACCESS BY INDEX ROWID| PURCHASE      |     1 |    46 |     2   (0)| 00:00:01 |
|*  2 |   INDEX UNIQUE SCAN         | PK_PURCHASENO |     1 |       |     1   (0)| 00:00:01 |
---------------------------------------------------------------------------------------------
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------
2 - access("PURCHASENO"=9989)

14 rows selected.

有人可以向我解释这意味着什么吗?

这是否意味着Oracle正在使用索引来执行此查询?

1 个答案:

答案 0 :(得分:1)

线索在计划中。

这意味着您可以独特地扫描索引PK_PURCHASENO。

| Operation         | Name          | Rows  |
---------------------------------------------
| INDEX UNIQUE SCAN | PK_PURCHASENO |     1 |

我假设这个名字是你的主键,并且根据你的查询判断它是在PURCHASENO列上。主键必须是唯一的,所以这并不奇怪。您注意到列表示您只返回一行,这确认了这一点.a

另一个重要的是这一行。

| Id  | Operation                   | Name          | Rows  | Bytes |
---------------------------------------------------------------------
|   1 |  TABLE ACCESS BY INDEX ROWID| PURCHASE      |     1 |    46 |

您已对索引进行了唯一扫描,但您不仅仅是从索引中选择数据,还必须在编写select *时从表中返回数据。 ROWID是表中标识行的唯一地址。通过它的ROWID访问(单个)行是返回数据的最快方法。 Oracle在主键索引中找到所需的行,然后使用rowid选择行的其余部分。您注意到 bytes 列有46,这意味着该行的长度为46个字节。

相反,如果您使用以下查询,则不再需要ROWID访问:

select purchaseno
  from purchase
 where purchaseno = 1000

这是因为PURCHASENO列已经在索引中;没有必要访问该表。 select *被认为是“有害的”,因为这样做不仅会增加您从磁盘读取的数据量,还可能增加您通过网络发送的数据量,但这也意味着您可能必须执行其他操作才能访问您的数据。只能选择你需要的行。

最后两点,在您的查询中,值PUCRHASENO用引号括起来,尽管它是一个数字。如果PURCHASENO实际上是一个角色,这很好,但是如果它是一个数字,你在这里冒险,因为你隐含地将角色转换为数字。 Oracle explicitly recommends against implicit conversion的原因如下:

  
      
  • 使用显式数据类型转换函数时,SQL语句更容易理解。

  •   
  • 隐式数据类型转换可能会对性能产生负面影响,尤其是当列值的数据类型转换为常量的数据类型而不是相反时。

  •   
  • 隐式转换取决于它发生的上下文,并且在每种情况下可能无法以相同的方式工作。例如,从datetime值到VARCHAR2值的隐式转换可能会返回意外的年份,具体取决于NLS_DATE_FORMAT的值   参数。

  •   
  • 隐式转换的算法可能会在软件版本和Oracle产品之间发生变化。显式转换的行为更具可预测性。

  •   

执行此可能会使优化程序混淆,以至于使用索引,尽管这在查询中不太可能像您那样简单。

最后,这是个人偏好,我发现PURCHASE表的主键名称相当混乱。更好的标准是PK_<table name>而不是PK_<column name>一个表只能有一个主键,并且该名称中只有一个对象可以在任何一个模式中。但是,可以使两个表具有与主键相同的列名。

Oracle性能调优指南有一章reading and understanding explain plans,我强烈建议您阅读。