Oracle 除非

Oracle 除非,oracle,join,cartesian,Oracle,Join,Cartesian,我有一个应该返回2行的查询。但是,它返回48行。它的行为就像一个被连接的表不存在一样。但是,如果我将该表中的一列添加到select子句中,而不更改查询的from或where部分,它将返回2行 下面是“解释计划”中没有选择“m.*”的内容: 在选择框中添加m.*后,再次显示: 有人能解释为什么它会这样吗 更新:我们只在一个系统上出现此问题,而在另一个系统上没有。DBA确认出现问题的是运行optimizer\u features\u enable set至10.2.0.5,而没有出现问题的是运行

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

下面是“解释计划”中没有选择“m.*”的内容:

在选择框中添加m.*后,再次显示:

有人能解释为什么它会这样吗


更新:我们只在一个系统上出现此问题,而在另一个系统上没有。DBA确认出现问题的是运行optimizer\u features\u enable set至10.2.0.5,而没有出现问题的是运行optimizer\u features\u enable set至10.2.0.4。不幸的是,客户站点正在运行10.2.0.5。

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

表消除(交替称为 “连接消除”)删除冗余 查询中的表。有一张桌子 如果其列仅为 在连接谓词中引用,以及 这是保证这些加入 既不过滤也不扩展 结果行。有几个 Oracle将消除 冗余表


也许这是一种相关的bug。看看这篇文章。

看起来像个bug。制约因素是什么

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

更进一步,如果MASTERSOURCE函数中的每一行都有一个或零个非OSDA行,那么它应该是排除的候选行。但是主源ID和名称之间也需要一对一


我将从ACCOUNTSOURCE中提取48行的rowid,然后跟踪MASTERSOURCE ID和名称,并查看这些行是基于什么原因被复制或不被排除的。也就是说,MASTERSOURCE中有12个重复的名称,通过NOVALIDATE约束,它们应该是唯一的。

它所做的是显而易见的:第一个查询删除了到
mastersources
MASTERSOURCE_函数的连接以及where子句中的过滤器。它为什么这样做是令人困惑的。更正,它已经删除了到
mastersources
的连接。在第一个查询中,它仍然在MF.function上有过滤器,但联接显然缺失。@Thomas,是的,我也这么认为,但百万美元的问题是为什么。如果颠倒联接的顺序,你能重现结果差异吗?@Thomas,查询最初是用accountsource顺序中的表编写的,mastersource、mastersource_函数、accountenrollment和我按照您上面看到的那样重新排序,以查看它是否有帮助。它没有。@Paul Tomblin:是否有任何相关的约束是NOVALIDATE和Relay的,并且有违反这些约束的数据?也许Oracle在认为可以的时候使用表消除,尽管它不应该这样做。(我还没能为此创建一个测试用例,但似乎应该可以让Oracle返回错误的结果。有人能举个例子来证明这一点吗?)是的,当query_rewrite_integrity参数设置为TRUSTED或STALE_TOLERATED时,依赖约束可能会发生这种情况。DBA的响应:我检查了建议的配置,特别是query_rewrite_参数(该参数不适用,因为我们没有使用物化视图,并且它设置为强制)并将_optimizer_transitivity_retain参数更改为true,这并没有什么区别。在第一种情况下,它的行为就像根本没有MASTERSOURCE联接一样,并且返回每个MASTERSOURCE函数行,并使用“NON-OSDA”,而不管sourcename是什么。我可以从计划中看到这一点。看到这些约束将表明它认为MASTERSOURCE联接是冗余的原因。