我很擅长索引和解释计划,所以请耐心等待! 我正在尝试调整查询,但我遇到了问题。
我有两张桌子:
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
第二次查询:
SELECT
*
FROM
AP21.IMPCOST_CLR
WHERE
CLRIDX = 100
第三次查询:
SELECT
*
FROM
AP21.SKU
INNER JOIN
AP21.IMPCOST_CLR ON
IMPCOST_CLR.CLRIDX = SKU.CLRIDX
答案 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