当前位置:  数据库>oracle

关于Oracle full outer join 的bug问题分析及处理

    来源: 互联网  发布时间:2017-05-15

    本文导语: full (outer) join是用来全连接两个表的语法。即希望将A表和B表关联,能够得到A表中有而B表中没有的记录,或者B表中有而A表中没有的记录。 如何判断是否有该记录,则通过on子句来关联。 下面是一个例子: SQL> with  2  A as(select 1...

full (outer) join是用来全连接两个表的语法。即希望将A表和B表关联,能够得到A表中有而B表中没有的记录,或者B表中有而A表中没有的记录。

如何判断是否有该记录,则通过on子句来关联。

下面是一个例子:

SQL> with
  2  A as(select 1 a, 2 b from dual),
  3  B as(select 2 a, 3 b from dual)
  4  select * from A full join B
  5      on A.a=B.a
  6  /
 
        A          B          A          B
---------- ---------- ---------- ----------
        1          2         
                                  2          3
 

了解了以上基本原理后,我们应该知道,理论上讲,A表和B表的在from子句中的顺序是没有关系的,也就是不影响结果。但是,实际上,却出现了这样的问题,下面是对这种情况的描述:

--------------------------------------------------------------------------------------------
| Id  | Operation                | Name            | Rows  | Bytes | Cost (%CPU)| Time    |
--------------------------------------------------------------------------------------------
|  0 | SELECT STATEMENT        |                | 12791 |  349K|    82  (3)| 00:00:01 |
|  1 |  VIEW                    |                | 12791 |  349K|    82  (3)| 00:00:01 |
|  2 |  UNION-ALL              |                |      |      |            |          |
|*  3 |    FILTER                |                |      |      |            |          |
|*  4 |    HASH JOIN RIGHT OUTER|                | 12790 |  1124K|    41  (3)| 00:00:01 |
|  5 |      TABLE ACCESS FULL  | JXC_RISHARESUM  |  1735 | 78075 |    7  (0)| 00:00:01 |
|  6 |      TABLE ACCESS FULL  | JXC_ALLTRADEDAY | 12790 |  562K|    33  (0)| 00:00:01 |
|*  7 |    HASH JOIN ANTI        |                |    1 |    76 |    41  (3)| 00:00:01 |
|*  8 |    TABLE ACCESS FULL    | JXC_RISHARESUM  |    1 |    45 |    7  (0)| 00:00:01 |
|  9 |    TABLE ACCESS FULL    | JXC_ALLTRADEDAY | 12790 |  387K|    33  (0)| 00:00:01 |
--------------------------------------------------------------------------------------------

 

从以上执行计划来看,在第四步骤,使用的是hash join rigth outer连接方式。而通过改变两表的摆放顺序,得到如下的执行计划:

 

-----------------------------------------------------------------------------------------
| Id  | Operation            | Name            | Rows  | Bytes | Cost (%CPU)| Time    |
-----------------------------------------------------------------------------------------
|  0 | SELECT STATEMENT      |                |  1876 | 52528 |    82  (3)| 00:00:01 |
|  1 |  VIEW                |                |  1876 | 52528 |    82  (3)| 00:00:01 |
|  2 |  UNION-ALL          |                |      |      |            |          |
|*  3 |    FILTER            |                |      |      |            |          |
|*  4 |    HASH JOIN OUTER  |                |  1874 |  164K|    41  (3)| 00:00:01 |
|  5 |      TABLE ACCESS FULL| JXC_RISHARESUM  |  1735 | 78075 |    7  (0)| 00:00:01 |
|  6 |      TABLE ACCESS FULL| JXC_ALLTRADEDAY | 12790 |  562K|    33  (0)| 00:00:01 |
|*  7 |    HASH JOIN ANTI    |                |    2 |  152 |    41  (3)| 00:00:01 |
|*  8 |    TABLE ACCESS FULL | JXC_ALLTRADEDAY |    2 |    90 |    33  (0)| 00:00:01 |
|  9 |    TABLE ACCESS FULL | JXC_RISHARESUM  |  1735 | 53785 |    7  (0)| 00:00:01 |
-----------------------------------------------------------------------------------------

 

注意,此时,执行计划中的第四个步骤,变成了:hash join outer方式。这个才是我们所期望的方式。那究竟是什么导致了这个变化呢?查看他们的谓词连接逻辑:

hash join right outer的:

  3 - filter(NVL("T1"."C_SHARENO","T2"."C_SHARENO")='26200703200004969020')
  4 - access("T2"."D_TRADEDATE"="T1"."D_TRADEDATE"(+) AND
              "T2"."D_REGDATE"="T1"."D_REGDATE"(+) AND "T2"."C_FUNDCODE"="T1"."C_FUNDCODE"(+) AND
              "T2"."C_FUNDACCO"="T1"."C_FUNDACCO"(+))
  7 - access("T2"."C_FUNDACCO"="T1"."C_FUNDACCO" AND
              "T2"."C_FUNDCODE"="T1"."C_FUNDCODE" AND "T2"."D_REGDATE"="T1"."D_REGDATE" AND
              "T2"."D_TRADEDATE"="T1"."D_TRADEDATE")
  8 - filter(NVL("T1"."C_SHARENO",NULL)='26200703200004969020')

 

hash join outer的:

  3 - filter(NVL("T1"."C_SHARENO","T2"."C_SHARENO")='26200703200004969020')
  4 - access("T2"."D_TRADEDATE"(+)="T1"."D_TRADEDATE" AND
              "T2"."D_REGDATE"(+)="T1"."D_REGDATE" AND "T2"."C_FUNDCODE"(+)="T1"."C_FUNDCODE"
              AND "T2"."C_FUNDACCO"(+)="T1"."C_FUNDACCO")
  7 - access("T2"."C_FUNDACCO"="T1"."C_FUNDACCO" AND
              "T2"."C_FUNDCODE"="T1"."C_FUNDCODE" AND "T2"."D_REGDATE"="T1"."D_REGDATE" AND
              "T2"."D_TRADEDATE"="T1"."D_TRADEDATE")
  8 - filter("T2"."C_SHARENO"='26200703200004969020')

还是没有发现明显的区别。但是实际却导致了结果的不同。

还原到原始的表连接顺序,然后对两表进行分析,再查看执行计划:

SQL> call dbms_stats.gather_table_stats(user, 'JXC_ALLTRADEDAY');

调用完成。

SQL> call dbms_stats.gather_table_stats(user, 'JXC_RISHARESUM');

.....

-----------------------------------------------------------------------------------------
| Id  | Operation            | Name            | Rows  | Bytes | Cost (%CPU)| Time    |
-----------------------------------------------------------------------------------------
|  0 | SELECT STATEMENT      |                |  1738 | 48664 |    82  (3)| 00:00:01 |
|  1 |  VIEW                |                |  1738 | 48664 |    82  (3)| 00:00:01 |
|  2 |  UNION-ALL          |                |      |      |            |          |
|*  3 |    FILTER            |                |      |      |            |          |
|*  4 |    HASH JOIN OUTER  |                |  1735 |  191K|    41  (3)| 00:00:01 |
|  5 |      TABLE ACCESS FULL| JXC_RISHARESUM  |  1735 | 98895 |    7  (0)| 00:00:01 |
|  6 |      TABLE ACCESS FULL| JXC_ALLTRADEDAY | 12775 |  698K|    33  (0)| 00:00:01 |
|*  7 |    HASH JOIN ANTI    |                |    3 |  276 |    41  (3)| 00:00:01 |
|*  8 |    TABLE ACCESS FULL | JXC_ALLTRADEDAY |    3 |  168 |    33  (0)| 00:00:01 |
|  9 |    TABLE ACCESS FULL | JXC_RISHARESUM  |  1735 | 62460 |    7  (0)| 00:00:01 |
-----------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

  3 - filter(NVL("T1"."C_SHARENO","T2"."C_SHARENO")='26200703200004969020')
  4 - access("T2"."D_TRADEDATE"(+)="T1"."D_TRADEDATE" AND
              "T2"."D_REGDATE"(+)="T1"."D_REGDATE" AND "T2"."C_FUNDCODE"(+)="T1"."C_FUNDCODE"
              AND "T2"."C_FUNDACCO"(+)="T1"."C_FUNDACCO")
  7 - access("T2"."C_FUNDACCO"="T1"."C_FUNDACCO" AND
              "T2"."C_FUNDCODE"="T1"."C_FUNDCODE" AND "T2"."D_REGDATE"="T1"."D_REGDATE" AND
              "T2"."D_TRADEDATE"="T1"."D_TRADEDATE")
  8 - filter("T2"."C_SHARENO"='26200703200004969020')

 

可发��,这时原来连接方式的错误执行计划被修正了,改为hash join outer连接。


    
 
 

您可能感兴趣的文章:

  • 在Redhat7.2+Oracle8i如果硬件配置中用P4处理器,对oracle的安装有没有影响(100分)
  • Oracle控制文件多元化处理
  • 关于ORACLE中执行批处理的问题
  • oracle删除文件后数据库启动不了的处理方法
  • MS Server和Oracle中对NULL处理的一些细节差异
  • ORACLE DATAGUARD中手工处理日志v$archive_GAP的方法
  • Oracle 10g中用FIRALL处理非连续数组
  • 重新安装主机后ORACLE DB的处理
  • 轻轻松松学会在Oracle中实现时间相加处理
  • Linux系统下导出ORACLE数据库出现Exporting questionable statistics.错误 处理
  • 处理Oracle数据库中杀不掉的锁
  • oracle 11g导出数据时报ORA 1455错误的处理方法
  • redhat 下 oracle proc 预处理总是留下 tpXXXXXX 的临时文件
  • Oracle时间精确到时、分、秒处理方案
  • 一次Oracle故障处理过程
  • Oracle 插入超4000字节的CLOB字段的处理方法
  • Oracle 10g中用FORALL处理非连续数组
  • Oracle对于死锁的处理方法
  • Oracle中关于处理小数点位数的几个函数
  • SQL Server和Oracle并行处理比较分析
  • java开源软件 iis7站长之家
  • 深入oracle特定信息排序的分析
  • oracle 数据库连接分析
  • Oracle移动数据文件到新分区步骤分析
  • 基于oracle小数点前零丢失的问题分析
  • Oracle date如何比较大小分析
  • Linux上建立第二个ORACLE实例分析
  • Oracle 数据库容灾复制解决方案分析Shar Plex
  • 计算机名称修改后Oracle不能正常启动问题分析及解决
  • oracle导出sql语句的结果集和保存执行的sql语句(深入分析)
  • linux as3 _weblogic8_oracle系统访问50万/日,常常ping不通,分析原因
  •  
    本站(WWW.)旨在分享和传播互联网科技相关的资讯和技术,将尽最大努力为读者提供更好的信息聚合和浏览方式。
    本站(WWW.)站内文章除注明原创外,均为转载、整理或搜集自网络。欢迎任何形式的转载,转载请注明出处。












  • 相关文章推荐
  • 问一个简单的问题,我装了oracle 8.05,我并没有发有发现JDBC这个目录,是不是我要下载jdbc for oracle。
  • Linux下的Oracle安装问题(非常问题)
  • Oracle 10g中导出到Oracle 9的问题小结
  • oracle JDBC的问题
  • Suse linux使用oracle问题
  • 请教: Javaswing 和 Oracle JDBC thin 连接的问题
  • oracle版本问题
  • 关于oracle的一个恼火的小问题!
  • Javabeen+oracle的问题
  • 安装ORACLE的问题
  • 再问java 连接oracle 问题,急!
  • Oracle 监听内存泄露问题
  • Oracle乱码问题
  • oracle环境变量保存问题求教
  • Oracle高级官员回答Sun雇员的问题
  • 请问一个oracle的jdbc问题
  • Jsp连接Oracle的问题 ???
  • oracle的job不能运行问题的解决方法
  • 请教JSP与ORACLE连接问题。
  • JAVA连接ORACLE问题(100分)
  • Oracle 12c发布简单介绍及官方下载地址
  • 在linux下安装oracle,如何设置让oracle自动启动!也就是让oracle那个服务自动启动,不是手动的
  • oracle 11g最新版官方下载地址
  • 请问su oracle 和su - oracle有什么不同?
  • Oracle 数据库(oracle Database)Select 多表关联查询方式
  • 虚拟机装Oracle R12与Oracle10g
  • Oracle数据库(Oracle Database)体系结构及基本组成介绍
  • Oracle 数据库开发工具 Oracle SQL Developer
  • 如何设置让Oracle SQL Developer显示的时间包含时分秒
  • Oracle EBS R12 支持 Oracle Database 11g
  • Oracle 10g和Oracle 11g网格技术介绍


  • 站内导航:


    特别声明:169IT网站部分信息来自互联网,如果侵犯您的权利,请及时告知,本站将立即删除!

    ©2012-2021,