11

我对索引和解释计划很陌生,所以请多多包涵!我正在尝试调整查询,但我遇到了问题。

我有两张桌子:

SKU
------
SKUIDX (Unique index)
CLRIDX (Index)
..
..

IMPCOST_CLR
-----------
ICCIDX (Unique index)
CLRIDX (Index)
...
..

当我执行 aselect * from SKU where clridx = 122时,我可以看到它正在使用解释计划中的索引(它说 TABLE ACCESS.. INDEX,它说 OBJECT_NAME 下的索引名称,选项是 RANGE SCAN)。

现在,当我尝试加入同一个字段时,它似乎没有使用索引(它说 TABLE ACCESS.. HASH JOIN 并且在选项下,它说 FULL)。

我应该寻找什么来尝试看看它为什么不使用索引?抱歉,我不确定要键入什么命令来显示此内容,所以如果您需要更多信息,请告诉我。

示例:
第一个查询:

  SELECT
    *
  FROM
    AP21.SKU
  WHERE
    CLRIDX = 100

在此处输入图像描述

第二个查询:

  SELECT
    *
  FROM
    AP21.IMPCOST_CLR
  WHERE
    CLRIDX = 100

在此处输入图像描述

第三个查询:

  SELECT
    *
  FROM
    AP21.SKU
  INNER JOIN
    AP21.IMPCOST_CLR ON
    IMPCOST_CLR.CLRIDX = SKU.CLRIDX

在此处输入图像描述

4

2 回答 2

22

看看这个查询:

SELECT
    *
FROM
    AP21.SKU
INNER JOIN
    AP21.IMPCOST_CLR ON
    IMPCOST_CLR.CLRIDX = SKU.CLRIDX

它没有额外的谓词。因此,您将 SKU 中的所有行连接到 IMPCOST_CLR 中的所有行。此外,您正在从两个表中选择所有列。

这意味着 Oracle 必须读取两个表的全部内容。最有效的方法是使用全表扫描,在多块读取中舀出所有行,并使用散列来匹配连接的值。

基本上,这是一个集合操作,这是 SQL 做得很好,而索引读取更多的是RBAR。现在,如果您更改了第三个查询以包含一个附加谓词,例如

WHERE SKU.CLRIDX = 100

您很可能会看到访问路径恢复为 INDEX RANGE SCAN 。因为您只选择了相对较少的行,所以索引读取再次成为更有效的路径。


“我试图调整的查询要长数百个,但要分解并逐步进行!”

这是一个很好的技术,但您需要了解 Oracle 优化器的工作原理。解释计划中有很多信息。 了解更多。 注意Rows每一步的列中的值。这告诉您优化器期望从操作中获得多少行。与第三个查询相比,您将看到前两个查询的值非常不同。

于 2013-07-16T01:31:41.970 回答
6

现在,当我尝试加入同一个字段时,它似乎没有使用索引(它说 TABLE ACCESS.. HASH JOIN 并且在选项下,它说 FULL)。

这是因为 HASH JOIN 在连接谓词上不使用(需要)索引:

http://use-the-index-luke.com/sql/join/hash-join-partial-objects

于 2013-07-16T05:57:51.150 回答