【问题标题】:Query does cartesian join unless查询做笛卡尔连接,除非
【发布时间】:2011-03-15 01:19:53
【问题描述】:

我有一个应该返回 2 行的查询。但是,它返回 48 行。它的行为就像正在加入的表之一不存在。但是,如果我将该表中的一列添加到 select 子句,而不更改查询的 from 或 where 部分,它将返回 2 行。

以下是“解释计划”在选择中没有“m.*”时所说的内容:

在选择中添加 m.* 后又是这样:

谁能解释为什么它应该这样表现?

更新:我们只在一个系统上遇到过这个问题,而在另一个系统上没有。 DBA 验证了有问题的运行 optimizer_features_enable 设置为 10.2.0.5,而没有发生问题的运行 optimizer_features_enable 设置为 10.2.0.4。不幸的是,客户站点运行的是 10.2.0.5。

【问题讨论】:

  • 它所做的很明显:第一个查询已经完全删除了与 mastersourcesmastersource_function 的连接以及 Where 子句中的过滤器。为什么这样做令人困惑。
  • 更正,它已删除与mastersources 的连接。在第一个查询中,它仍然在 MF.function 上有过滤器,但显然缺少连接。
  • @Thomas,是的,我也是这么想的,但百万美元的问题就是为什么。
  • 如果颠倒连接的顺序,是否能够重现结果差异?
  • @Thomas,查询最初是使用按 accountsource、mastersource、mastersource_function、accountenrollment 顺序的表编写的,我按照您在上面看到的重新排序,看看它是否有帮助。它没有。

标签: oracle join cartesian


【解决方案1】:

这是关于 10gR2 中引入的联接消除:

表消除(也称为 “加入消除”)删除多余的 查询中的表。一张桌子是 如果其列仅是多余的 在连接谓词中引用,并且 保证那些加入 既不过滤也不扩展 结果行。有几种 甲骨文将消除的情况 冗余表。

也许这是某种相关的错误。看看this 的文章。

【讨论】:

  • @Paul Tomblin:是否存在 NOVALIDATE 和 RELY 的相关约束,并且有违反约束的数据?也许 Oracle 在认为可以时使用表消除,即使它不应该这样做。 (我无法为此创建一个测试用例,但似乎应该可以让 Oracle 返回错误的结果。有人有例子来证明这一点吗?)
  • 是的,当 query_rewrite_integrity 参数设置为 TRUSTED 或 STALE_TOLERATED 时,依赖约束可能会发生这种情况。
  • 来自我们 DBA 的回复:我检查了建议的配置,特别是 query_rewrite_parameter(它不适用,因为我们没有使用物化视图并且它被设置为强制执行)并将 _optimizer_transitivity_retain 参数更改为 true这并没有什么不同。
【解决方案2】:

看起来像一个错误。有什么限制?

从逻辑上讲,如果 MASTERSOURCE_FUNCTION 中的所有行都具有函数 NON-OSDA,则不会排除任何行(或者如果没有任何行具有该值,则将排除所有行)。

更进一步,如果 MASTERSOURCE 中的每一行在 MASTERSOURCE_FUNCTION 中都有一个或零个 NON-OSDA 行,那么它应该是排除的候选对象。但 MASTERSOURCE ID 和 NAME 之间也需要一对一。

我将从 ACCOUNTSOURCE 中提取 48 行的 ROWID,然后跟踪 MASTERSOURCE ID 和 NAME 并查看这些行被复制或未排除的原因。也就是说,在 MASTERSOURCE 中是否有 12 个重复的名称,通过 NOVALIDATE 约束预计它是唯一的。

【讨论】:

  • 在第一种情况下,它就像根本没有 MASTERSOURCE 连接一样,并且无论源名称是什么,都返回每个带有“NON-OSDA”的 MASTERSOURCE_FUNCTION 行。
  • 我可以从计划中看出这一点。查看约束将表明它为什么认为 MASTERSOURCE 连接是多余的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-07-13
  • 2014-08-24
  • 2010-10-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-02-21
相关资源
最近更新 更多