[英]Oracle 12c Subquery Factoring Inline View now has bad plan?
Update 11/2 更新11/2
After some additional troubleshooting, my team was able to tie this Oracle bug directly to a parameter change that was made on the 12c
database the night before the query stopped working. 经过一些额外的故障排除后,我的团队能够将此Oracle错误直接与查询停止工作前一天在12c
数据库上进行的参数更改联系起来。 After experiencing some performance issues from an application tied to this database, my team had our DBA change the OPTIMIZER_FEATURES_ENABLE
parameter from 12.1.02
to 11.2.0.4
. 在遇到与此数据库12.1.02
的应用程序的一些性能问题后,我的团队让我们的DBA将OPTIMIZER_FEATURES_ENABLE
参数从12.1.02
为11.2.0.4
。 This fixed the performance issue for the problem application but caused the bug I have described above. 这解决了问题应用程序的性能问题,但导致了我上面描述的错误。 To verify, I've been able to replicate this same issue in a separate environment by changing this parameter. 为了验证,我已经能够通过更改此参数在单独的环境中复制相同的问题。 My DBA has filed a ticket with Oracle to have this looked at. 我的DBA已向Oracle提交了一张机票,以便对此进行查看。
As a workaround, I was able to make a slight change to my query in order to retrieve the expected results. 作为一种解决方法,我能够对我的查询稍作更改,以便检索预期的结果。 Specifically, I combined Subquery1
with Subquery2
and I moved a few predicates in Subquery1
from the WHERE
clause to the JOIN
(where they more properly belonged). 具体地讲,我结合Subquery1
与Subquery2
和我在移动几个谓词Subquery1
从WHERE
子句到JOIN
(在那里它们更恰当地属于)。 This change edited my execution plan (it is slightly less efficient than what was listed before) but was enough to address the original issue. 此更改编辑了我的执行计划(它的效率略低于之前列出的效率)但足以解决原始问题。
Original Post 原帖
Firstly, let me apologize for any vagueness in this question but I'm dealing with a confidential financial system so I am forced to hide certain implementation details. 首先,让我为这个问题中的任何模糊道歉,但我正在处理一个机密的金融系统,所以我被迫隐藏某些实施细节。
Background 背景
I have an Oracle
query that I put into production a long time ago that has recently stopped producing expected results coincidentally after an upgrade from 11g
to 12c
. 我有一个很久以前投入生产的Oracle
查询,它最近在从11g
升级到12c
之后不久产生了预期的结果。 To my (and my production support team's) knowledge this query had been working fine for well over a year before that. 对于我(以及我的生产支持团队)的知识,这个查询在此之前已经运行了一年多。
Details 细节
The query is overly complicated and not very efficient but this is in large part because I am dealing with non-normalized tables (historically modeled after a Mainframe) and poor data input from upstream systems. 查询过于复杂且效率不高,但这在很大程度上是因为我正在处理非规范化表(历史上以大型机为模型)和来自上游系统的较差数据输入。 In order to deal with a complicated business situation I leveraged multiple levels of Subquery Factoring (the WITH
statement) and then my final statement joins together two Inline Views. 为了处理复杂的业务情况,我利用了多个级别的子查询因子( WITH
语句),然后我的最终语句将两个内联视图连接在一起。 The basic structure of the query without all of the complicated predicates is as follows: 没有所有复杂谓词的查询的基本结构如下:
I have 3 tables Table1
, Table2
, Table3
. 我有3个表Table1
, Table2
, Table3
。 Table1
is a processing table made up of records from Table2
. Table1
是由表Table2
的记录组成的处理表。
--This grabs a subset from Table1
WITH Subquery1 as (
SELECT FROM Table1),
--This eliminates certain records from the first subset based on sister records
--from the original source table
Subquery2 as (
SELECT FROM Subquery1
WHERE NOT EXISTS FROM (SELECT from Table2)),
--This ties the records from Subquery2 to Table3
Subquery3 as (
SELECT FROM Table3
JOIN (SELECT Max(Date) FROM Table3)
JOIN Subquery2)
--This final query evaluates subquery3 in two different ways and
--only takes those records which fit the criteria items from both sets
SELECT FROM
(SELECT FROM Subquery3) -- Call this Inline View A
JOIN (SELECT FROM Subquery3) -- Call this Inline View B
The final query is pretty basic: 最后的查询非常基本:
SELECT A.Group_No, B.Sub_Group, B.Key, B.Lob
FROM (SELECT Group_No, Lob, COUNT(Sub_Group)
FROM Subquery3
GROUP BY Group_No, Lob
HAVING COUNT(Sub_Group) = 1) A
JOIN (SELECT Group_No, Sub_Group, Key, Lob
FROM Subquery3
WHERE Sub_Group LIKE '0000%') B
ON A.Group_No = B.Group_No
AND A.Lob = B.Lob
Problem 问题
If I edit the final query to remove the second Inline View and evaluate the output of the A
inline view, I come away with 0 returned rows . 如果我编辑最终查询以删除第二个内联视图并评估A
内联视图的输出,我将返回0返回的行 。 I've manually evaluated the records for each individual subquery and can confirm this is an expected result. 我手动评估了每个子查询的记录,并确认这是预期的结果。
Likewise, if I edit the final query to produce the output of only the 'B' inline view, I come away with 6 returned rows . 同样,如果我编辑最终查询以仅生成“B”内联视图的输出,那么我将返回6个返回的行 。 Again, I've manually evaluated the data and this is exactly as expected. 我再次手动评估了数据,这与预期完全一致。
Now when joining these two subsets (Inline View A
and Inline View B
) together, I would expect that the final query result would be 0 rows (since an inner join between a full set and an empty set produces no matches). 现在,当将这两个子集(内联视图A
和内联视图B
)连接在一起时,我希望最终查询结果为0行(因为完整集和空集之间的内部连接不会产生匹配)。 However, when I run the entire query with the inner join as described above, I am getting back 1158 rows ! 但是,当我如上所述使用内部联接运行整个查询时, 我将返回1158行 !
I have reviewed the Execution Plan but nothing jumps out at me: 我已经审查了执行计划,但没有任何事情发生在我身上:
Questions 问题
Clearly I have done something to confuse the Oracle Optimizer and the updated query plan is pulling back a much different query than the one I have submitted. 很明显,我已经做了一些事情来混淆Oracle Optimizer,而更新的查询计划正在拉回一个与我提交的查询截然不同的查询。 My best guess is that with all of these temporary views floating around within the same query, I have confused Oracle into evaluating some set before one that it depends upon. 我最好的猜测是,所有这些临时视图都在同一个查询中浮动,我让Oracle混淆了在依赖它之前评估一些集合。
To this day I've been unable to locate the official Oracle documentation around the WITH
statement so I've never been completely confident about the order that subqueries are evaluated. 到目前为止,我一直无法找到围绕WITH
语句的官方Oracle文档,因此我从未对子查询的评估顺序充满信心。 I did notice in searching SO ( can't find it now ) someone mentioned that a factored subquery cannot refer to another factored query. 我确实注意到搜索SO( 现在找不到 )有人提到一个因子子查询不能引用另一个因子查询。 I've never known this to be true before but the bizarre output above is making me wonder if I had only been lucky before with this query? 我以前从来不知道这是真的,但上面那个奇怪的输出让我想知道我之前是否只有这个查询才幸运?
Can anyone explain the behavior I am seeing? 谁能解释我所看到的行为? Am I attempting to do something obviously incorrect with this query plan? 我是否尝试使用此查询计划做一些明显不正确的事情? Or alternatively, is there any chance that something changed between 11g and 12c that could explain why the behavior of this query might have changed? 或者,是否有可能在11g和12c之间发生变化,这可以解释为什么这个查询的行为可能已经改变了?
This sounds like a "wrong results" bug in Oracle. 这听起来像Oracle中的“错误结果”错误。 These bugs are usually extremely specific to the version and the features you are using. 这些错误通常非常特定于您使用的版本和功能。 There's nothing obviously wrong with the queries or execution plan you posted. 您发布的查询或执行计划没有明显错误。
You have two ways of handling this: 您有两种处理方式:
DUAL
. 您还需要删除所有对象并仅使用DUAL
。 This process can take hours. 此过程可能需要数小时。 At the end, when you're left with only a few lines of code, either post them here, look on Oracle Support, or create a Service Request. 最后,当您只剩下几行代码时,请在此处发布,查看Oracle支持或创建服务请求。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.