【问题标题】:Oracle subquery with MAX operator taking very long带有 MAX 运算符的 Oracle 子查询需要很长时间
【发布时间】:2014-11-23 19:34:21
【问题描述】:

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

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 将 ALL 运算符替换为 NOT EXISTS:

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

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

【问题讨论】:

  • 为什么你认为tableA.id = (SELECT MAX (id) FROM TABLE_JOIN_XX tableB WHERE tableA.id = tableB.id) 等于tableA.id &gt;= ALL (SELECT id FROM TABLE_JOIN_XX tableB WHERE tableA.id = tableB.id)
  • id 实际上是一个 id_parent,我现在更正了查询。从概念上讲,如果 A >= 每个(元素集),则 A = MAX(元素集)
  • 谢谢,我忘了。

标签: sql oracle


【解决方案1】:

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

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) 上的索引应该对这个查询更有帮助。

【讨论】:

  • 对不起,我在这里复制查询时出错了。 where 条件上的 id 实际上是一个 id_parent,否则就没有意义。 tableA 和 tableB 具有相同的 id_parent,我从 tableA 中选择 id = 与同一父级相关的最大 id 的元素
猜你喜欢
  • 2016-04-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-02-02
  • 2018-01-09
  • 2015-05-17
相关资源
最近更新 更多