Sql Oracle 12c子查询分解内联视图现在有错误的计划?

Sql Oracle 12c子查询分解内联视图现在有错误的计划?,sql,oracle,inline-view,query-planner,subquery-factoring,Sql,Oracle,Inline View,Query Planner,Subquery Factoring,更新11/2 经过一些额外的故障排除,我的团队能够将这个Oracle错误直接与查询停止工作前一天晚上对12c数据库所做的参数更改联系起来。在遇到与此数据库相关的应用程序的一些性能问题后,我的团队让DBA将OPTIMIZER\u FEATURES\u ENABLE参数从12.1.02更改为11.2.0.4。这修复了问题应用程序的性能问题,但导致了我上面描述的错误。为了验证,我已经能够通过更改此参数在单独的环境中复制相同的问题。我的DBA已经向Oracle提交了一份申请单,要求对其进行检查 作为一种

更新11/2

经过一些额外的故障排除,我的团队能够将这个Oracle错误直接与查询停止工作前一天晚上对
12c
数据库所做的参数更改联系起来。在遇到与此数据库相关的应用程序的一些性能问题后,我的团队让DBA将
OPTIMIZER\u FEATURES\u ENABLE
参数从
12.1.02
更改为
11.2.0.4
。这修复了问题应用程序的性能问题,但导致了我上面描述的错误。为了验证,我已经能够通过更改此参数在单独的环境中复制相同的问题。我的DBA已经向Oracle提交了一份申请单,要求对其进行检查

作为一种变通方法,我能够对查询做一些细微的更改,以检索预期的结果。具体地说,我将
子查询1
子查询2
相结合,并将
子查询1
中的一些谓词从
WHERE
子句移动到
JOIN
(它们更合适地归属于该子句)。这一变化编辑了我的执行计划(它的效率比之前列出的略低),但足以解决最初的问题


原创帖子

首先,请允许我为这个问题中的任何含糊不清表示歉意,但我处理的是一个机密的金融系统,因此我不得不隐藏某些实现细节

背景

我有一个早就投入生产的
Oracle
查询,在从
11g
升级到
12c
后,最近碰巧停止了生成预期结果。据我(和我的生产支持团队)所知,在那之前的一年多时间里,这个查询一直运行良好

详细信息

查询过于复杂,效率也不是很高,但这在很大程度上是因为我处理的是非规范化表(历史上以大型机为模型)和来自上游系统的糟糕数据输入。为了处理复杂的业务情况,我利用了多级子查询分解(带语句的
),然后我的final语句将两个内联视图连接在一起。没有所有复杂谓词的查询的基本结构如下:

我有3个表
表1
表2
表3
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
最终查询非常基本:

   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
问题

如果编辑最后一个查询以删除第二个内联视图并计算
A
内联视图的输出,则返回的行数为0。我已经手动评估了每个子查询的记录,并且可以确认这是一个预期的结果

同样,如果我编辑最后一个查询以只生成“B”内联视图的输出,我会得到6个返回行。同样,我已经手动评估了数据,这与预期完全一致

现在,当将这两个子集(内联视图
A
和内联视图
B
)连接在一起时,我希望最终的查询结果是0行(因为完整集和空集之间的内部连接不会产生匹配)。但是,当我使用上述内部联接运行整个查询时,我将返回1158行

我已经审查了执行计划,但没有任何事情让我感到意外:

问题

很明显,我做了一些事情来混淆Oracle优化器,更新后的查询计划收回了一个与我提交的查询大不相同的查询。我最好的猜测是,由于所有这些临时视图都在同一个查询中浮动,我把Oracle弄糊涂了,在它所依赖的某个集合之前先对其求值

到目前为止,我还无法找到有关
WITH
语句的Oracle官方文档,因此我从未对子查询的求值顺序有过完全的信心。我在搜索时注意到,所以(现在找不到)有人提到一个分解子查询不能引用另一个分解查询。我以前从来都不知道这是真的,但上面奇怪的输出让我想知道我以前是否只是幸运地使用了这个查询

有人能解释我看到的行为吗?我是否试图用这个查询计划做一些明显不正确的事情?或者,是否有可能在11g和12c之间发生某种变化,从而解释为什么此查询的行为可能发生了变化?

这听起来像是Oracle中的“错误结果”错误。这些bug通常与您所使用的版本和功能极其相关。您发布的查询或执行计划没有明显的问题

您有两种处理方法:

  • 试着找出准确的bug。您对常用表表达式所做的操作看起来不错。很少有时候,您的查询在技术上是无效的,您在一个版本中获得“幸运”并且它可以工作,而当您升级它失败时。但当这种情况发生时,新版本通常会抛出错误,而不会返回错误的结果。可能是您使用的一些非常奇怪、特定的功能组合导致了这个问题。要找到真正的问题,您需要大量简化查询,直到您可以进行尽可能小的更改,并看到问题出现和消失。您还需要删除所有对象,并且只使用
    DUAL
    。这个过程可能需要几个小时。最后,当您只剩下几行代码时,可以在此处发布它们,查看Oracle支持,或者创建服务请求
  • 避免该错误。即使您完成了上述步骤,也可能没有修复方法。萨米特