Oracle在加入时不使用索引

时间:2013-07-16 00:53:37

标签: performance oracle join indexing query-optimization

我很擅长索引和解释计划,所以请耐心等待! 我正在尝试调整查询,但我遇到了问题。

我有两张桌子:

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

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

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

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

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

示例:
第一个查询:

  SELECT
    *
  FROM
    AP21.SKU
  WHERE
    CLRIDX = 100

enter image description here

第二次查询:

  SELECT
    *
  FROM
    AP21.IMPCOST_CLR
  WHERE
    CLRIDX = 100

enter image description here

第三次查询:

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

enter image description here

2 个答案:

答案 0 :(得分:18)

看看这个查询:

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 Optimzer的工作原理。解释计划中有很多信息。 Find out more.请注意每个步骤Rows列中的值。这告诉您Optimizer期望从操作中获得多少行。与第三个查询相比,前两个查询将看到非常不同的值。

答案 1 :(得分:6)

  

现在,当我尝试加入相同的字段时,它不会出现   使用索引(它表示TABLE ACCESS .. HASH JOIN和下   选项,它说完全)。

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

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