oracle半连接与反向连接的详细解决方案
当两个表的连接,如果在1号线是否专注的结果需要根据表2或不可能至少有一个数据表中的数据匹配判断,这会发生和半连接;抗耦合半连接的补充,他们将作为共同的数据库连接方法如嵌套循环,合并排序,哈希连接选项。事实上,半联轴器和反向连接本身也可以认为是两种耦合方法;在CBO模式优化,优化器可以根据灵活转换的执行语句的实际情况实现半连接和抗耦合的方法,毕竟,不是SQL语法可以明确称为半连接反向连接,他们只是满足一些SQL语句时,优化器可以选择的选项,但仍需要这两个选项的进一步的性能优势将在特定的情况下。
半挂车
半连接通常在相关子含有存在于查询的使用,为任何和相同的使用,所以会有一半的连接;但也有例外,在11gR2版本,优化器不列入或为子查询选择半连接的任何分支,这现在只有确定约束的官方文件,几个场景:
复制代码代码如下所示:
相关子项使用关键字查询嵌套循环>半连接
SQL >选择department_name
2从hr.departments系
3在department_id(选择从中department_id hr.employees EMP);
选择11行。
执行计划
----------------------------------------------------------
计划哈希值:2605691773
----------------------------------------------------------------------------------------
我的名字|操作| | |行| |字节成本(CPU)时间| |
----------------------------------------------------------------------------------------
| 0 | SELECT语句| | | | 10 190 3(0)| 00:00:01 |
1嵌套循环半| | | | | | 10 190 3(0)| 00:00:01 |
2表访问全|部门| | | | | 27 432 3(0)| 00:00:01 |
3索引范围扫描| * | | emp_department_ix | | | 41 123 0(0)| 00:00:01 |
----------------------------------------------------------------------------------------
谓词信息(由操作ID标识):
离开
3访问(department_id=department_id )
统计
----------------------------------------------------------
0递归调用
0分贝块得到
11一致的获取
0物理读
0重做日志大小
742个字节通过网络发送给客户机
从客户端接收的524个字节
2 SQL*Net切换到/从客户端
0类(内存)
0类(磁盘)
11行处理
相关子类使用存在的关键字查询嵌套循环>半连接
SQL >选择department_name
2从hr.departments部存在
3(选择空从EMP在hr.employees emp.department_id = dept.department_id);
选择11行。
执行计划
----------------------------------------------------------
计划哈希值:2605691773
----------------------------------------------------------------------------------------
我的名字|操作| | |行| |字节成本(CPU)时间| |
----------------------------------------------------------------------------------------
| 0 | SELECT语句| | | | 10 190 3(0)| 00:00:01 |
1嵌套循环半| | | | | | 10 190 3(0)| 00:00:01 |
2表访问全|部门| | | | | 27 432 3(0)| 00:00:01 |
3索引范围扫描| * | | emp_department_ix | | | 41 123 0(0)| 00:00:01 |
----------------------------------------------------------------------------------------
谓词信息(由操作ID标识):
离开
3 -访问(EMP。department_id=部。department_id )
统计
----------------------------------------------------------
1递归调用
0分贝块得到
11一致的获取
0物理读
0重做日志大小
742个字节通过网络发送给客户机
从客户端接收的524个字节
2 SQL*Net roundtrips to/from client
0类(内存)
0类(磁盘)
11行处理
谓词或用于存在子查询=禁用半连接的分支中。
SQL >选择department_name
2从hr.departments系
3在1 = 2或存在
4(选择空从EMP在hr.employees emp.department_id = dept.department_id);
选择11行。
执行计划
----------------------------------------------------------
计划哈希值:440241596
----------------------------------------------------------------------------------------
我的名字|操作| | |行| |字节成本(CPU)时间| |
----------------------------------------------------------------------------------------
| 0 | SELECT语句| | | | 27 432 4(0)| 00:00:01 |
|×1 |滤波器| | | | | |
2表访问全|部门| | | | | 27 432 3(0)| 00:00:01 |
3索引范围扫描| * | | emp_department_ix | | | 2 6 1(0)| 00:00:01 |
----------------------------------------------------------------------------------------
谓词信息(由操作ID标识):
离开
1过滤器(存在)(从HR中选择0。雇员EMP在哪里)
EMP。department_id=:B1))
3 -访问(EMP。department_id=:B1)
统计
----------------------------------------------------------
1递归调用
0分贝块得到
35一致的获取
0物理读
0重做日志大小
742个字节通过网络发送给客户机
从客户端接收的524个字节
2 SQL*Net切换到/从客户端
0类(内存)
0类(磁盘)
11行处理
从结果集中,我们可以很容易地联想到内部链接,那么为什么半关联通常会得到更高的性能呢关键是半连接的优化,以嵌套循环为例,在嵌套循环连接,驱动表是由进入内圈配合需要阅读,只有当每行数据行外环和内环的匹配操作的数据采集是一个结果集,年底前完成;及半相对差加入数据集是只返回一次记录每个1,不管数据集在几个匹配的记录,因此,在子查询匹配到治疗结束后的数据来提高性能,发现第一个半连接。
在某些情况下,需要半连接来提高性能,我们可以控制的半连接,手动的执行计划,并使用半连接和no_semijoin提示指定使用和禁用半连接的优化。
复制代码代码如下所示:
- no_semijoin提示禁用半连接的使用
SQL >选择department_name
2从hr.departments系
3在哪里department_id(选择no_semijoin * / / *从department_id hr.employees EMP +);
选择11行。
执行计划
----------------------------------------------------------
计划哈希值:3372191744
------------------------------------------------------------------------------------------
我的名字|操作| | |行| |字节成本(CPU)时间| |
------------------------------------------------------------------------------------------
| 0 | SELECT语句| | | | 106 1802 4(25)| 00:00:01 |
| 1 |观| vm_nwvw_2 | | | 106 1802 4(25)| 00:00:01 |
| 2 |哈希独特的| | | | 106 2544 4(25)| 00:00:01 |
| 3 |嵌套循环| | | | 106 2544 3(0)| 00:00:01 |
4表访问全|部门| | | | | 27 567 3(0)| 00:00:01 |
5索引范围扫描| * | | emp_department_ix | | | 4 12 0(0)| 00:00:01 |
------------------------------------------------------------------------------------------
谓词信息(由操作ID标识):
离开
5访问(department_id=department_id )
统计
----------------------------------------------------------
506递归调用
0分贝块得到
188一致的获取
7物理读
0重做日志大小
742个字节通过网络发送给客户机
从客户端接收的524个字节
2 SQL*Net切换到/从客户端
10类(内存)
0类(磁盘)
11行处理
此外,我们还可以使用_always_semi_join隐藏参数选择的半连接的连接类型,并为_always_semi_join参数的可选值:
复制代码代码如下所示:
SQL >选择
2 parno_kspvld_values pvalid_par #,
3 name_kspvld_values pvalid_name,
4 value_kspvld_values pvalid_value,
5解码(isdefault_kspvld_values,假',',' pvalid_default 'default)
6从
7 X kspvld_values美元
8在哪里
9下(name_kspvld_values)像%| |低(NVL('pname ',name_kspvld_values)| | '%')
10阶的
11 pvalid_par #,
12 pvalid_default,
13 pvalid_value
14 /
PAR #参数的默认值
---------------------------------------------------------------------------------------------
1705 _always_semi_join选择
_always_semi_join哈希
_always_semi_join合并
_always_semi_join nested_loops
_always_semi_join关闭
这个参数的默认值是选择的,这表明半连接的类型由优化器决定。接下来,我们使用_always_semi_join参数改变上述嵌套循环半加入哈希连接半连接。
复制代码代码如下所示:
-默认嵌套循环
SQL >选择department_name
2从hr.departments系
3在department_id(选择从中department_id hr.employees EMP);
选择11行。
执行计划
----------------------------------------------------------
计划哈希值:2605691773
----------------------------------------------------------------------------------------
我的名字|操作| | |行| |字节成本(CPU)时间| |
----------------------------------------------------------------------------------------
| 0 | SELECT语句| | | | 10 190 3(0)| 00:00:01 |
1嵌套循环半| | | | | | 10 190 3(0)| 00:00:01 |
2表访问全|部门| | | | | 27 432 3(0)| 00:00:01 |
3索引范围扫描| * | | emp_department_ix | | | 41 123 0(0)| 00:00:01 |
----------------------------------------------------------------------------------------
谓词信息(由操作ID标识):
离开
3访问(department_id=department_id )
统计
----------------------------------------------------------
0递归调用
0分贝块得到
11一致的获取
0物理读
0重做日志大小
742个字节通过网络发送给客户机
从客户端接收的524个字节
2 SQL*Net切换到/从客户端
0类(内存)
0类(磁盘)
11行处理
-会话级修改参数
SQL >改变会话设置_always_semi_join=合并;
会议改变。
-合并半连接
SQL >选择department_name
2从hr.departments系
3在department_id(选择从中department_id hr.employees EMP);
选择11行。
执行计划
----------------------------------------------------------
计划哈希值:954076352
--------------------------------------------------------------------------------------------------
我的名字|操作| | |行| |字节成本(CPU)时间| |
--------------------------------------------------------------------------------------------------
| 0 | SELECT语句| | | | 10 190 4(25)| 00:00:01 |
1合并加入半| | | | | | 10 190 4(25)| 00:00:01 |
| 2表访问的索引rowid |部门| | | | 27 432 2(0)| 00:00:01 |
3索引全扫描| | | dept_id_pk | 27 | | 1(0)| 00:00:01 |
|×4 |般独特的| | | | 107 321 2(50)| 00:00:01 |
5索引全扫描| | | emp_department_ix | | | 107 321 1(0)| 00:00:01 |
--------------------------------------------------------------------------------------------------
谓词信息(由操作ID标识):
离开
4访问(department_id=department_id )
滤波器(department_id=department_id )
统计
----------------------------------------------------------
1递归调用
0分贝块得到
5一致的获取
1物理读
0重做日志大小
742个字节通过网络发送给客户机
从客户端接收的523个字节
2 SQL*Net切换到/从客户端
1类(内存)
0类(磁盘)
11行处理
-从跟踪中选择优化器仍然非常可靠。
分离
实质上,反向连接和半连接的许多类似的因素,反键通常用于含不在,不存在,子查询一样,如果子查询谓词或分支,反向链接也将被禁用,它主要不是和半连接或同一点返回的数据匹配,它不过在子查询返回的数据行,但原理是相同的,找到第一个匹配的记录,并立即停止处理以提高子查询的效率,它是建立在现场:
复制代码代码如下所示:
SQL > AutoTrace traceonly
不在触发后连接
SQL >选择department_name
2从hr.departments
3在department_id不
4(选择department_id从哪里department_id hr.employees不为空);
选择16行。
执行计划
----------------------------------------------------------
计划哈希值:3082375452
----------------------------------------------------------------------------------------
我的名字|操作| | |行| |字节成本(CPU)时间| |
----------------------------------------------------------------------------------------
| 0 | SELECT语句| | | | 17 323 3(0)| 00:00:01 |
1嵌套循环抗| | | | | | 17 323 3(0)| 00:00:01 |
2表访问全|部门| | | | | 27 432 3(0)| 00:00:01 |
3索引范围扫描| * | | emp_department_ix | | | 41 123 0(0)| 00:00:01 |
----------------------------------------------------------------------------------------
谓词信息(由操作ID标识):
离开
3访问(department_id=department_id )
滤波器(department_id不为空)
统计
----------------------------------------------------------
1递归调用
0分贝块得到
12一致的获取
6物理读
0重做日志大小
985个字节通过网络发送给客户机
从客户端接收的535个字节
3 SQL*Net切换到/从客户端
0类(内存)
0类(磁盘)
16行处理
-存在触发反连接
SQL >选择department_name
2从hr.departments系
3在不存在
4(选择空从EMP在hr.employees emp.department_id = dept.department_id);
选择16行。
执行计划
----------------------------------------------------------
计划哈希值:3082375452
----------------------------------------------------------------------------------------
我的名字|操作| | |行| |字节成本(CPU)时间| |
----------------------------------------------------------------------------------------
| 0 | SELECT语句| | | | 17 323 3(0)| 00:00:01 |
1嵌套循环抗| | | | | | 17 323 3(0)| 00:00:01 |
2表访问全|部门| | | | | 27 432 3(0)| 00:00:01 |
3索引范围扫描| * | | emp_department_ix | | | 41 123 0(0)| 00:00:01 |
----------------------------------------------------------------------------------------
谓词信息(由操作ID标识):
离开
3 -访问(EMP。department_id=部。department_id )
统计
----------------------------------------------------------
3递归调用
0分贝块得到
13一致的获取
0物理读
0重做日志大小
985个字节通过网络发送给客户机
从客户端接收的535个字节
3 SQL*Net切换到/从客户端
0类(内存)
0类(磁盘)
16行处理
可以从负和外连接操作上述例子可以达到相同的效果出色,但从实施计划,减去操作显然不是反向连接操作的优化,并使用外部联接虽然反向连接优化,但由于与空值的虚拟记录匹配数据的使用,不容易理解,因此,实际使用不推荐。
如果您想手动控制反耦合执行计划,也可以使用一些提示和参数,常用的提示有:
1.ANTIJOIN- is in reverse connection, and the optimizer determines the connection type
2.use_anti岁的提示版,与antijoin功能一致
3。{ nl_aj } { } { } - hash_aj merge_aj | |指定型抗耦合(10g开始被抛弃,但仍然有效)
在参数控制方面,还有一个_always_anti_join参数是_always_semi_join非常相似,它的使用是完全一样的。有参数_optimizer_null_aware_antijoin和_optimizer_outer_to_anti_enable控制空值和外部连接之间的反向连接转化。
复制代码代码如下所示:
-使用提示显式指定反连接的类型。
SQL >选择department_name
2从hr.departments系
3在不存在(选择hash_aj空从hr.employees EMP / * +。
4在emp.department_id = dept.department_id);
选择16行。
执行计划
----------------------------------------------------------
计划哈希值:3587451639
----------------------------------------------------------------------------------------
我的名字|操作| | |行| |字节成本(CPU)时间| |
----------------------------------------------------------------------------------------
| 0 | SELECT语句| | | | 17 323 5(20)| 00:00:01 |
1哈希连接抗| * | | | | | 17 323 5(20)| 00:00:01 |
2表访问全|部门| | | | | 27 432 3(0)| 00:00:01 |
3索引全扫描| | | emp_department_ix | | | 107 321 1(0)| 00:00:01 |
----------------------------------------------------------------------------------------
谓词信息(由操作ID标识):
离开
1 -访问(EMP。department_id=部。department_id )
统计
----------------------------------------------------------
566 recursive calls
0分贝块得到
193一致的获取
0物理读
0重做日志大小
985个字节通过网络发送给客户机
从客户端接收的535个字节
3 SQL*Net切换到/从客户端
12类(内存)
0类(磁盘)
16行处理
使用_optimizer_null_antijoin参数关闭后的空值考虑连接选项,返回空值不使用反向连接
SQL >改变会话设置_optimizer_null_aware_antijoin=假;
会议改变。
SQL >选择department_name
2从hr.departments
3在department_id没有(选择department_id人力资源。员工);
没有行选择
执行计划
----------------------------------------------------------
计划哈希值:3416340233
----------------------------------------------------------------------------------
我的名字|操作| | |行| |字节成本(CPU)时间| |
----------------------------------------------------------------------------------
| 0 | SELECT语句| | | | 26 416 30(0)| 00:00:01 |
|×1 |滤波器| | | | | |
2表访问全|部门| | | | | 27 432 3(0)| 00:00:01 |
3表访问全|员工| * | | | | 2 6 2(0)| 00:00:01 |
----------------------------------------------------------------------------------
谓词信息(由操作ID标识):
离开
1过滤器(不存在)(从HR中选择0。雇员雇员)
在lnnvl(department_id < >:B1)))
3过滤器(lnnvl(department_id < >:B1))
统计
----------------------------------------------------------
1递归调用
0分贝块得到
172一致的获取
0物理读
0重做日志大小
343个字节通过网络发送给客户机
从客户端接收的513个字节
1 SQL*Net切换到/从客户端
0类(内存)
0类(磁盘)
0行处理