首页 > 数据库 >Oracle反连接和外连接中NESTED LOOPS无法更改驱动表

Oracle反连接和外连接中NESTED LOOPS无法更改驱动表

时间:2023-06-16 14:35:14浏览次数:54  
标签:00 tt 连接 LOOPS TT 00.01 NESTED col

 

Oracle反连接和外连接中NESTED LOOPS无法更改驱动表

 

先说反连接,现有SQL如下:

select t.* from t where t.col not in (select /*+ nl_aj */ tt.col from tt where tt.col is not null) and t.col is not null;
Plan hash value: 1434981293

-------------------------------------------------------------------------------------
| Id  | Operation          | Name | Starts | E-Rows | A-Rows |   A-Time   | Buffers |
-------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT   |      |      1 |        |      1 |00:00:00.01 |      17 |
|   1 |  NESTED LOOPS ANTI |      |      1 |      1 |      1 |00:00:00.01 |      17 |
|*  2 |   TABLE ACCESS FULL| T    |      1 |      2 |      2 |00:00:00.01 |       7 |
|*  3 |   TABLE ACCESS FULL| TT   |      2 |      2 |      1 |00:00:00.01 |      10 |
-------------------------------------------------------------------------------------

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

   2 - filter("T"."COL" IS NOT NULL)
   3 - filter(("TT"."COL" IS NOT NULL AND "T"."COL"="TT"."COL"))

 

 

id=3是对以对主表T做全表扫描应用谓词条件得到数据作为结果集1,然后将结果集1中依次每行数据根据条件(t.col=tt.col and tt.col is not null)来匹配表TT的数据,当一旦只要在表TT有一行满足(t.col=tt.col and tt.col is not null)的时候,表T的这行数据就是不要的会直接遗弃然后继续对下一行进行同样的流程一直到结果集1全部数据都进行一遍,这是“NESTED LOOPS ANTI”过程的简单描述。

反证法:假设现在表TT作为驱动表,我虚拟构造一个执行计划如下:

先执行id=3对表TT全表扫描并过滤出tt.col is not null的数据作为结果集1,然后将结果集1中依次每行数据根据条件(tt.col=t.col and t.col is not null)来匹配表T的数据,当有满足条件条件(tt.col=t.col and t.col is not null)的时候,证明匹配的表T(注意不是表TT)的那一批满足条件的数据都是不要的,那除了这一批数据以外表T剩下的其他数据呢?你无法判断剩余的其他数据是否会和结果集1还没进行匹配的行能否匹配的上,因此表TT作为驱动表的算法是无法进行下去的。

虚假的执行计划:
--------------------------------------------------------------------------------------------
| Id  | Operation                 | Name | Starts | E-Rows | A-Rows |   A-Time   | Buffers |
--------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT          |      |      1 |        |      1 |00:00:00.01 |      16 |
|   1 |  SORT AGGREGATE           |      |      1 |      1 |      1 |00:00:00.01 |      16 |
|   2 |   NESTED LOOPS RIGHT ANTI |      |      1 |      1 |      1 |00:00:00.01 |      16 |
|*  3 |    TABLE ACCESS FULL      | TT   |      1 |      2 |      2 |00:00:00.01 |       6 |
|*  4 |    TABLE ACCESS FULL      | T    |      2 |      2 |      1 |00:00:00.01 |      10 |
--------------------------------------------------------------------------------------------

 

 

另外,再《基于Oracle的SQL优化》一书中P58明确提出,反连接中主表一定是驱动表,次表为被驱动表。

 

也可以换另外一个角度看,反连接满足一定条件是可以改写为left join形式的,比如上边的:select t.* from t where t.col not in (select /*+ nl_aj */ tt.col from tt where tt.col is not null) and t.col is not null;

可以改写为select /*+ use_nl(tt) */ t.* from t left join tt on t.col = tt.col where tt.col is null and t.col is not null;

这个时候以left join角度看也可以得出驱动表一定是表T。

关于left join,且看下边。

 

说说外连接,以左连接为例子,现有SQL如下:

右边强制表TT做驱动表,但是无法生效。

                                                                                        强制是不生效的:
select /*+ use_nl(tt) */ t.col,tt.col from t left join tt on t.col=tt.col;              select /*+ leading(tt) use_nl(t tt) */ t.col,tt.col from t left join tt on t.col=tt.col;
Plan hash value: 3672464008                                                             Plan hash value: 3672464008
                                                                                        
-------------------------------------------------------------------------------------   -------------------------------------------------------------------------------------
| Id  | Operation          | Name | Starts | E-Rows | A-Rows |   A-Time   | Buffers |   | Id  | Operation          | Name | Starts | E-Rows | A-Rows |   A-Time   | Buffers |
-------------------------------------------------------------------------------------   -------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT   |      |      1 |        |      3 |00:00:00.01 |      25 |   |   0 | SELECT STATEMENT   |      |      1 |        |      3 |00:00:00.01 |      25 |
|   1 |  NESTED LOOPS OUTER|      |      1 |      3 |      3 |00:00:00.01 |      25 |   |   1 |  NESTED LOOPS OUTER|      |      1 |      3 |      3 |00:00:00.01 |      25 |
|   2 |   TABLE ACCESS FULL| T    |      1 |      3 |      3 |00:00:00.01 |       7 |   |   2 |   TABLE ACCESS FULL| T    |      1 |      3 |      3 |00:00:00.01 |       7 |
|*  3 |   TABLE ACCESS FULL| TT   |      3 |      1 |      1 |00:00:00.01 |      18 |   |*  3 |   TABLE ACCESS FULL| TT   |      3 |      1 |      1 |00:00:00.01 |      18 |
-------------------------------------------------------------------------------------   -------------------------------------------------------------------------------------
                                                                                        
Predicate Information (identified by operation id):                                     Predicate Information (identified by operation id):
---------------------------------------------------                                     ---------------------------------------------------
                                                                                        
   3 - filter(("TT"."COL" IS NOT NULL AND "T"."COL"="TT"."COL"))                           3 - filter(("TT"."COL" IS NOT NULL AND "T"."COL"="TT"."COL"))

 

为什么表TT无法强制作为驱动表?

其实很好理解,从外连接的定义看就知道了,外连接(Outer Join)是对内连接的一种拓展,它是指表连接的连接结果除了包含那些完全满足连接条件的记录之外还会包含驱动表中所有不满足该连接条件的记录

而外连接就包含了左连接,防偷以上边例子看,最终表T的数据是全部都会出现再最终结果里边,那么表T肯定是全表扫描来最终一次性获取到整表的数据。

若是用表TT做驱动表,会产生多次对表T的全表扫描外,最终主表T的不满足连接条件的记录如何界定?毕竟满足条件的也是表TT的结果集中一条一条根据tt.col=t.col找出来而不是一次性的。

而且,从定义里边已经规定了驱动表必须就是表T了。

 

标签:00,tt,连接,LOOPS,TT,00.01,NESTED,col
From: https://www.cnblogs.com/PiscesCanon/p/17485434.html

相关文章

  • 为什么连接集成在企业的数智平台里是“刚需”?
    某省烟草公司原有900多个财务人员从事核算工作,在其财务软件与17家银行进行在线集成后,银行单证回单与财务系统中的单据实现了自动生成、自动对账、自动关联、自动归档等,投产当年即减少了180个财务人员,剩下的财务核算工作量比重也从原来的70%降低至20%,从重复性事务工作中解脱出来的财......
  • Oracle外连接等价于反连接的情况
     Oracle外连接等价于反连接的情况 在Oracle外连接等价于内连接的情况中提到了外连接中被驱动表的字段作为谓词条件出现在where中,并且不为isnull的话,等价于内连接。当外连接中被驱动表的连接列作为谓词条件出现在where中,且是做isnull过滤,若select出现的列都属于驱动表的时......
  • 问题解决sql文件上传和蚁剑连接
    1.无法连接上自己的ip:发现问题是上传的木马不在127.0.0.1的文件下时,会导致解析不到木马,要将木马上传到127.0.0.1的文件下连接2.解决sql上传一句话木马问题要先在mysql的配置文件my.ini中添加导入导出数据库的地址:secure_file_priv=D:\phpstudy_pro\WWW然后重启数据库,可以进行sq......
  • Oracle外连接等价于内连接的情况
     Oracle外连接等价于内连接的情况 实际之前有过研究,Oracle外连接的执行计划中没有出现OUTER的例子,现在展开来讲。以左连接为例子,有SQL如下:左边的执行计划中id=2并带有OUTER,表示不是外连接。右边的执行计划和左边的执行计划一模一样,证明左边的SQL完全等价与右边的SQL。se......
  • BLE中GAP层中广播、扫描、连接等概念在LL层的具体实现
    BLE中GAP层中广播、扫描、连接等概念在LL层的具体实现在spec中GAP的章节里对广播、扫描、连接的概念进行了说明。但缺乏具体实现的解释。Vol3:CoreSystemPackage[Hostvolume]PartC:GenericAccessProfile而在LL层章节中则提供了相关GAP相关数据包交互的流程。Vol......
  • Windows Server 2022 安装配置 MYSQL 及远程连接
    官方下载地址:https://dev.mysql.com/downloads/mysql/解压后新建my.ini放在解压目录下。配置环境变量:此电脑->属性->高级系统设置->环境变量->系统变量。找到path,新建D:\ProgramFiles\mysql-8.0.33-winx64\bin[mysqld]#设置3306端口port=3306#设置mysql的安装目录based......
  • 外连接消除技术应用
    上回介绍了外连接消除技术。今天更进一步来聊聊这个话题。select*fromarightjoinbona.m1=b.m1leftjoinconc.c1=b.c1wherec.c1in(1,2,3);基于外连接消除技术,这个语句leftjoin可以改写成innerjoin:select*fromarightjoinbona.m1=b.m1......
  • 【SQL 优化器技术系列】 外连接消除
    Oracle2005年出了一个30多页的小册子,《QueryOptimizationinOracleDatabase10gRelease2》,介绍了常见的优化器技术。我是做SQL执行的,优化部分只了解皮毛,从没有系统学习过。本系列逐个学习和介绍,自我提升,也帮助他人。外连接消除就是将一个outerjoin转换成innerjoin。......
  • 数据库连接池-Druid的使用
       packagedruid;/**druid数据连接池**/importcom.alibaba.druid.pool.DruidDataSourceFactory;importjavax.sql.DataSource;importjava.io.FileInputStream;importjava.io.FileReader;importjava.sql.Connection;importjava.util.Properties;p......
  • Mysql查看连接数(连接总数、活跃数、最大并发数)
    查看最大连接数mysql>showvariableslike'%max_connection%';+-----------------------+-------+|Variable_name|Value|+-----------------------+-------+|extra_max_connections|||max_connections|2512|+----------------......