关于Oracle full outer join 的bug问题分析及处理
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问题分析及处理相关推荐
- 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 ...
- oracle sql outer join,解答Oracle LEFT JOIN和LEFT OUTER JOIN的区别
问:我一直在对不同种类的Oracle连接做研究,目前还搞不清楚LEFT JOIN和LEFT OUTER JOIN之间有什么区别.Outer这个词是可选的么?因为Oracle中的LEFT JOIN是默认 ...
- Oracle Partition Outer Join 稠化报表
partition outer join实现将稀疏数据转为稠密数据,举例: with t as(select deptno, job, sum(sal) sum_sal from emp group ...
- oracle中右表有过滤条件的left outer join
oracle中left outer join就是以左表作为基表来进行连接操作,连接的结果中一定会涵盖基表中所有的列,即使有某些列与右表找不到匹配关系.如下分别是city表和stds表中的数据截图: ...
- Oracle数据库:oracle外连接left/right/full outer join on,oracle扩展的左右外连接展示符号(+)
Oracle数据库:oracle外连接left/right/full outer join on,oracle扩展的左右外连接展示符号(+) 2022找工作是学历.能力和运气的超强结合体,遇到寒冬,大 ...
- 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 使用 ...
- mysql全关联_MySQL实现全关联 full outer join
SQL LEFT JOIN 关键字 LEFT JOIN 关键字会从左表 (table_name1) 那里返回所有的行,即使在右表 (table_name2) 中没有匹配的行. LEFT JOIN 关键 ...
- 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= ...
- [20170816]Join Elimination Bug.txt
[20170816]Join Elimination Bug.txt https://jonathanlewis.wordpress.com/2017/08/14/join-elimination-b ...
最新文章
- Github 上特别火的 7 个学习 Python 编程的开源仓库
- python mysql绑定变量_python 数据库绑定变量
- 将pdf转换html_pdf文件怎么转换成html网页格式?用什么方法来转换?
- 持续集成工具Hudson安装实例
- 基于vue+mint-ui的mobile-h5的项目说明
- java 启动redis服务器_docker启动redis并使用java连接
- Caffe机器学习框架
- exists查询慢_8个SQL查询效率优化原则
- Linux自建yum仓及相关知识详解
- c语言uefi读写文件,UEFI简单的应用程序模块MyHelloWorld:C源文件/INF工程文件源码/简析[6]...
- 计算机编程入门先学什么最好?
- neo4j-入门---学习复杂关系使用CQL语句操作图数据库(二)
- 产品数据管理(PDM)技术说明书
- linux rsync文件夹增量同步
- LVGL - 在STM32上的移植
- java 有序的list_Java 中的 List —— 有序序列
- UE4 跑酷游戏-得分机制
- 吉尔布雷斯的动作研究—《可以量化的管理学》
- 北大计算机python教程_清华北大计算机系 联合推出的Java+Python1010集视频学习教程曝光...
- uni-app设置标题名字