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

Are non-relating subselects in Oracle calculated before outer statement?

经过长时间的搜索google 所以我仍然没有找到任何有关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是如何计算subselect的?使用 MINUS 而不是 subselect 会更好吗? [我的表非常大,意味着 10 万行]

Oracle 有一个非常好的优化器。它会决定先select子查询数据还是on-the-fly。在内部,它可以完全 re-write 您的查询并从多种方式中选择获取数据。

有时对我们来说很明显,DBMS 应该首先加载数据,然后将此列表用作 look-up,这就是我们在完成此任务时会做的事情。但是,对于 DBMS,另一种方法可能会好得多。

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

显而易见的答案是 - 这取决于。

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

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

Subqueries are nested when they appear in the WHERE clause of the parent statement. When Oracle Database evaluates a statement with a nested subquery, it must evaluate the subquery portion multiple times and may overlook some efficient access paths or joins.

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

Subquery unnesting unnests and merges the body of the subquery into the body of the statement that contains it, allowing the optimizer to consider them together when evaluating access paths and joins. The optimizer can unnest most subqueries, with some exceptions.
...
Assuming no restrictions exist, the optimizer automatically unnests some (but not all) of the following nested subqueries:
- Uncorrelated IN subqueries

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