Oracle 中的非相关子选择是不是在外部语句之前计算?

Posted

技术标签:

【中文标题】Oracle 中的非相关子选择是不是在外部语句之前计算?【英文标题】:Are non-relating subselects in Oracle calculated before outer statement?Oracle 中的非相关子选择是否在外部语句之前计算? 【发布时间】:2016-01-06 11:13:08 【问题描述】:

经过长时间的搜索 google 和 SO,我仍然没有找到关于 Oracle 中非相关子选择计算的任何信息。

我有需要找出差异的情况,我正在考虑使用这样的查询,其中子选择独立于外部查询:

select pk
from A
where pk is not in 
  (select from complex_query_with_many_joins )   -- non related quite complex query with many joins

我在 mysql 中读到最高 5.5(它们随着 5.6 的变化而变化),即使外部的每一行都是非真实的,也会计算子选择。

oracle 如何计算子选择?使用MINUS 而不是子选择会更好吗? [我的表非常大,意味着 100Ks 行]

【问题讨论】:

【参考方案1】:

Oracle 有一个非常好的优化器。它将决定是先选择子查询数据还是即时选择子查询数据。在内部,它可以完全重写您的查询,并从多种方式中选择获取数据。

有时对我们来说似乎很明显 DBMS 应该首先加载数据,然后使用这个列表作为查找,这就是我们在完成这项任务时会做的事情。但是,对于 DBMS,另一种方式可能会更好。

您的 IN 子句很好。它非常易读,我认为没有理由改变它。但是,如果您发现 MINUS 更具可读性,请改用它。使您的查询尽可能简单易读。依靠 Oracle 的优化器找到最佳执行计划。只有在遇到性能问题时,您才应该考虑重新编写查询 - 以便向优化器显示另一个选项:-)

【讨论】:

【参考方案2】:

显而易见的答案是 - 视情况而定。

始终查看执行计划,然后查看实际光标 (DBMS_XPLAN.DISPLAY_CURSOR),然后您会看到发生了什么以及按什么顺序。如果您想查看更多,请进行 10053 跟踪并查看优化器所做的所有考虑。 Oracle 在其优化器方面有无数优化。

【讨论】:

【参考方案3】:

这取决于子查询在做什么以及优化器是否可以取消嵌套它。 From the documentation:

子查询出现在父语句的 WHERE 子句中时是嵌套的。当 Oracle 数据库评估带有嵌套子查询的语句时,它必须多次评估子查询部分,并且可能会忽略一些有效的访问路径或连接。

这表明它将多次执行子查询,但接着说:

子查询取消嵌套将子查询的主体取消嵌套并合并到包含它的语句的主体中,从而允许优化器在评估访问路径和连接时将它们一起考虑。优化器可以取消嵌套大多数子查询,但有一些例外。 ... 假设不存在任何限制,优化器会自动取消嵌套以下嵌套子查询中的一些(但不是全部): - 不相关的 IN 子查询

作为@ThorstenKettner,您的示例看起来不错,但您始终可以检查执行计划显示的内容,或跟踪查询以了解其在幕后所做的详细信息。

【讨论】:

以上是关于Oracle 中的非相关子选择是不是在外部语句之前计算?的主要内容,如果未能解决你的问题,请参考以下文章

子查询

如何在外部选择语句中使用 row_number 分区?

创建在外部进程中运行的 WPF“控件”

oracle中的update语句能用相关子查询么?

选择语句中的子查询如何在 oracle 中工作

oracle入门之对表数据查询