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连接。

转载于:https://blog.51cto.com/cuug520/1436153

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

  1. oracle full outer join,oracle 内连接(inner join)、外连接(outer join)、全连接(full join)...

    建表语句: create table EMPLOYEE ( EID NUMBER, DEPTID NUMBER, ENAME VARCHAR2(200) ) create table DEPT ( D ...

  2. oracle sql outer join,解答Oracle LEFT JOIN和LEFT OUTER JOIN的区别

    问:我一直在对不同种类的Oracle连接做研究,目前还搞不清楚LEFT JOIN和LEFT OUTER JOIN之间有什么区别.Outer这个词是可选的么?因为Oracle中的LEFT JOIN是默认 ...

  3. Oracle Partition Outer Join 稠化报表

    partition outer join实现将稀疏数据转为稠密数据,举例: with t as(select deptno, job, sum(sal) sum_sal from emp group ...

  4. oracle中右表有过滤条件的left outer join

    oracle中left outer join就是以左表作为基表来进行连接操作,连接的结果中一定会涵盖基表中所有的列,即使有某些列与右表找不到匹配关系.如下分别是city表和stds表中的数据截图:   ...

  5. Oracle数据库:oracle外连接left/right/full outer join on,oracle扩展的左右外连接展示符号(+)

    Oracle数据库:oracle外连接left/right/full outer join on,oracle扩展的左右外连接展示符号(+) 2022找工作是学历.能力和运气的超强结合体,遇到寒冬,大 ...

  6. Oracle学习笔记(三)。连接查询。等值连接,非等值连接,自连接,LEFT OUTER JOIN,RIGHT JOIN,FULL JOIN,自然连接,内连接 INNERJOIN

    文章目录 1. 什么是多表查询 2. 多表链接方式 3. 多表连接语法 3.1 语法结构 3.2 定义连接 3.3 原则 4. 等值连接-内连接 4.1 什么是等值连接 4.2 抉择矩阵 4.3 使用 ...

  7. mysql全关联_MySQL实现全关联 full outer join

    SQL LEFT JOIN 关键字 LEFT JOIN 关键字会从左表 (table_name1) 那里返回所有的行,即使在右表 (table_name2) 中没有匹配的行. LEFT JOIN 关键 ...

  8. SQL中的left outer join,inner join,right outer join用法 (左右内连接)

    SQL语句中的left outer join,inner join,right outer join用法 left outer join=left join ,   right outer join= ...

  9. [20170816]Join Elimination Bug.txt

    [20170816]Join Elimination Bug.txt https://jonathanlewis.wordpress.com/2017/08/14/join-elimination-b ...

最新文章

  1. Github 上特别火的 7 个学习 Python 编程的开源仓库
  2. python mysql绑定变量_python 数据库绑定变量
  3. 将pdf转换html_pdf文件怎么转换成html网页格式?用什么方法来转换?
  4. 持续集成工具Hudson安装实例
  5. 基于vue+mint-ui的mobile-h5的项目说明
  6. java 启动redis服务器_docker启动redis并使用java连接
  7. Caffe机器学习框架
  8. exists查询慢_8个SQL查询效率优化原则
  9. Linux自建yum仓及相关知识详解
  10. c语言uefi读写文件,UEFI简单的应用程序模块MyHelloWorld:C源文件/INF工程文件源码/简析[6]...
  11. 计算机编程入门先学什么最好?
  12. neo4j-入门---学习复杂关系使用CQL语句操作图数据库(二)
  13. 产品数据管理(PDM)技术说明书
  14. linux rsync文件夹增量同步
  15. LVGL - 在STM32上的移植
  16. java 有序的list_Java 中的 List —— 有序序列
  17. UE4 跑酷游戏-得分机制
  18. 吉尔布雷斯的动作研究—《可以量化的管理学》
  19. 北大计算机python教程_清华北大计算机系 联合推出的Java+Python1010集视频学习教程曝光...
  20. uni-app设置标题名字

热门文章

  1. python与excel做数据可视化-python数据可视化怎么做?excel可视化图表制作?
  2. map中的迭代删除操作注意问题
  3. 网络编程学习笔记(shutdown函数)
  4. 题目1166:迭代求立方根
  5. T2821 天使之城 codevs
  6. Codeforces 758C. Unfair Poll
  7. win8.1配置java环境个人 win8.1
  8. Gnome Subtitles:字幕编辑器
  9. OpenCV中对图像数据进行64F和8U转换的方法
  10. sqlserver中判断表或临时表是否存在