-1
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 正在使用索引来执行此查询?

4

1 回答 1

1

线索在计划中。

这意味着您正在唯一地扫描索引 PK_PURCHASENO。

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

我假设这是您的主键,并根据您的查询判断它位于 PURCHASENO 列上。主键必须是唯一的,所以这不足为奇。您注意到rows列表示您只返回一行,这证实了这一点。

另一个重要的事情是这条线。

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

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

如果您改为使用以下查询,则不再需要通过 ROWID 进行访问:

select purchaseno
  from purchase
 where purchaseno = 1000

这是因为 PURCHASENO 列已经在索引中;无需访问该表。select *因此,它被认为是“有害的”,它不仅会增加您必须从磁盘读取的数据量以及可能需要通过网络发送的数据量,而且还意味着您可能需要执行额外的操作为了访问您的数据。只选择您需要的行。

最后两点,在您的查询中,值 PUCRHASENO 用引号括起来,尽管它是一个数字。如果 PURCHASENO 是,实际上是一个字符,这很好,但如果它是一个数字,你会在这里冒险,因为你正在隐式地将字符转换为数字。Oracle明确建议不要使用隐式转换,原因如下:

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

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

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

  • 隐式转换的算法可能会随着软件版本和 Oracle 产品的变化而变化。显式转换的行为更可预测。

这样做可能会使优化器感到困惑,以至于您使用索引,尽管在像您这样简单的查询中不太可能发生这种情况。

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

Oracle 性能调优指南有一章是关于阅读和理解解释计划的,我强烈推荐阅读。

于 2013-05-18T11:18:48.717 回答