带有MAX运算符的Oracle子查询占用很长时间

时间:2014-09-29 11:57:17

标签: sql oracle

我有一个使用非常复杂的数据库视图的Web应用程序来检索一些看似非常慢的数据,最多只需要3分钟即可完成。经过彻底调查后,我发现问题的原因是什么。 在我的代码中,我在WHERE子句中使用以下条件来仅检索连接表的LAST元素:

SELECT ...
FROM MY_TABLE
JOIN TABLE_JOIN_XX tableA on ....
..lots of other joins ...
WHERE
 tableA.id = 
   (SELECT MAX (id) FROM TABLE_JOIN_XX tableB WHERE tableA.id_parent = tableB.id_parent)

然后我按以下方式更改了条件:

 tableA.id >= ALL 
   (SELECT id FROM TABLE_JOIN_XX tableB WHERE tableA.id_parent = tableB.id_parent)

现在查询只需几秒钟。

现在我想知道为什么使用MAX运算符和ALL运算符之间的执行时间存在巨大差异。我确实很惊讶。我不是DBA,也不是查询优化的专家,但也许有些东西我不知道,在开发数据库访问查询时我应该考虑。

或者可能是某个特定Oracle实例中的问题而不是查询?我从来没有在同一个数据库的其他实例中发现过这个问题。

看一下解释计划我注意到在第二种情况下(而不是在第一种情况下),Oracle用NOT EXISTS替换ALL运算符:

 not exists 
  (select 0 from TABLE_JOIN_XX tableA 
     where tableA.id_parent=:b1 and LNNVL (id<=:b2))

有什么建议吗? 非常感谢。

1 个答案:

答案 0 :(得分:2)

您的查询似乎格式不正确。这是你的陈述:

WHERE tableA.id = (SELECT MAX(id) FROM TABLE_JOIN_XX tableB WHERE tableA.id = tableB.id)

您正在列id上执行相关子查询。然后您选择最大值。子查询只能返回tableA.idNULL,因此这相当于:

WHERE EXISTS (SELECT 1 FROM TABLE_JOIN_XX tableB WHERE tableA.id = tableB.id)

也许甲骨文有点困惑。在任何情况下,通过使用MAX(),您说需要处理所有值,因此Oracle可能正在这样做。实际上,它只需要找到一个带有值的行。

TABLE_JOIN_XX(id)上的索引应该可以帮助更多查询。