oracle表连接基础笔记

表连接

1.表连接顺序

不管目标 SQL 中有多少个表做表连接,Oracle 在实际执行该 SQL 时都只先两两做表连接,再依次执行这样的两两表连接过程,直到目标 SQL 中所有的表都已连接完毕。所以从严格意义上来说,这里的表连接顺序包含两层含义:一层含义是当两个表做表连接时,优化器需要决定这两个表中谁是驱动表 (outer table),谁是被驱动表 (inner table); 另外一层含义是当多表(超过两个以上的表)做表连接时,优化器需要决定这些表中谁和谁先做表连接,然后决定这个表连接结果所在的结果集再和剩余表中的哪一个再做表连接,这个两两做表连接的过程会一直持续下去,直到目标SOL中所有的表都已连接完为止。

2.表连接方法

在 Oracle 数据库中,两个表之间的表连接方法有排序合并连接、套循环连接、哈希连接和笛卡儿连接这四种,所以优化器在解析含表连接的目标 SOL 时,都需要从上述四种方法中选择一种,作为每一对表两两做表连接时所需要采用的方法。

2.1排序合并连接

排序合并连接(Sort Merge Join)是一种两个表在做表连接时用排序操作 (Sort)和并作 (Merge)来得到连接结果集的表连接方法。
如果两个表(这里将它们分别命名为表 T1和表 T2在做表连接时使用的是排序合并连接,则 Oracle 会依次顺序执行如下步骤。
(1)首先以目标 SOL 中指定的谓词条件(如果有的话去访问表 T1,然后对访问结果按照表 T1中的连接列来排序,排好序后的结果集我们记为结果集1
(2)接着以目标SOL 中指定的谓词条件(如果有的话)去访问表 T2,然后对访问结果按照表 T2中的连接列来排序,排好序后的结果集我们记为结果集2。
(3)最后对结果集1和结果集 2 执行合并操作,从中取出匹配记录来作为排序合并连接的最终执行结果。

对于排序合并连接的优缺点及适用场景,总结如下。
·通常情况下,排序合并连接的执行效率会远不如哈希连接,但前者的使用范围更广,因为哈希连接通常只能用于等值连接条件,而排序合并连接还能用于其他连接条件(例如<、<=、>、>=)·通常情况下,排序合并连接并不适合 OLTP 类型的系统,其本质原因是因为对于OLTP 类型的系统而言,排序是非常昂贵的操作,当然,如果能避免排序操作,那么即使是 OLTP 类型的系统,也还是可以使用排序合并连接的。比如两个表虽然是做排序合并连接,但实际上它们并不需要排序,因为这两个表在各自的连接列上都存在索引。
从严格意义上说,排序合并连接并不存在驱动表的概念,虽然个人认为在执行合并的过程中,实际上还是存在驱动表和被驱动表的。

2.2嵌套循环连接

嵌套循环连接 (Nested Loops Join)是一种两个表在做表连接时依靠两层套循环(分别为外层循环和内层循环)来得到连接结果集的表连接方法。
如果两个表(这里将它们分别命名为表 T1和表 T2在做表连接时使用的是循环连接,则Oracle 会依次顺序执行如下步骤。
(1)首先,优化器会按照一定的规则来决定表 T1和 T2中是驱动表谁是被动表。驱动表用于外层循环,被驱动表用于内层循环。这里假设驱动表是T1,被驱动表是T2。
2)接着以目标 SOL中指定的谓词条件(如果有的话)去访问驱动表 T1,访问驱动表 T1后得到的结果集我们记为驱动结果集1。
(3)然后遍历驱动结果集1并同时遍历被驱动表 T2,即先取出驱动结果集1中的第1条记录,接着遍历被驱动表 T2 并按照连接条件去判断 T2 中是否存在匹配的记录,然后再取出驱动结果集 1中的第 2条记录按照同样的连接条件再去遍历被驱动表 T2 并判断 T2中是否还存在配的记录,直到遍历完动结果集1中所有的记录为止。这里的外层循环是指遍历驱动结果集 1所对应的循环,内层循环是指遍历被驱动表 T2 所对应的循环。显然,外层循环所对应的驱动结果集1有多少条记录,遍历被驱动表 T2 的内层循环就要做多少次这就是所谓的“嵌套循环”的含义。

对于嵌套循环连接的优缺点及适用场景,我们有如下总结。

  • 从上述嵌套循环连接的具体执行过程可以看出:如果驱动表所对应的驱动结果集的记录数较少,同时在被驱动表的连接列上又存在唯一性索引(或者在被驱动表的连接列上存在选择性很好的非唯一性索引),那么此时使用嵌套循环连接的执行效率就会非常高:但如果驱动表所对应的驱动结果集的记录数很多,即便在被驱动表的连接列上存在索引,此时使用嵌套循环连接的执行效率也不会高。
  • 只要驱动结果集的记录数较少,那就具备了做嵌套循环连接的前提条件,而驱动结果集是在对驱动表应用了目标 SOL 中指定的谓词条件(如果有的话)后所得到的结果集,所以大表也可以作为嵌套循环连接的驱动表,关键看目标 SQL 中指定的谓词条件(如果有的话)能否将驱动结果集的数据量降下来
  • 嵌套循环连接有其他连接方法所没有的一个优点:嵌套循环连接可以实现快速响应,即它可以第一时间先返回已经连接过且满足连接条件的记录,而不必等待所有的连接操作全部做完后才返回连接结果虽然排序合并连接和哈希连接也可以先返回已经连接过且满足连接条件的记录,而不必等待所有的连接操作都做完,但是它们并不是第一时间返回,因为排序合并连接要等到排完序后做合并操作时才能开始返回数据,而哈希连接则要等到驱动结果集所对应的 Hash Table 全部建完后才能开始返回数据。

为了提高嵌套循环连接的执行效率,在 Oracle 11g 中,Oracle 引入了向量 /0 (Vector /0)。在引入向量/0 后,Oracle 就可以将原先一批单块读所需要耗费的物理 /O 组合起来,然后用一个向量 /O 去批量处理它们,这样就实现了在单块读的数量不降低的情况下减少这些单块读所需要耗费的物理 I/O 数量,也就提高了嵌套循环连接的执行效率。

2.3哈希连接

哈希连接(Hash Join)是一种两个表在做表连接时主要依靠哈希运算来得到连接结果集的表连接方法
在 Oracle 7.3之前,Orale 数据库中的常用表连接方法就只有排序合并连接和套循环连接这两种,但这两种方法都各有其明显缺陷。对于排序合并连接,如果两个表在施加了目标 SOL 中指定的谓词条件(如果有的话)后得到的结果集很大且需要排序,则排序合并连接的执行效率一定不高:而对于嵌套循环连接,如果驱动表所对应的驱动结果集的记录数很大,即便在被驱动表的连接列上存在索引,此时使用嵌套循环连接的执行效率也会同样不高
为了解决排序合并连接和嵌套循环连接在上述情形下执行效率不高的问题,同时也为了给优化器提供一种新的选择,Orace 在 Oracle 7.3 中引入了哈希连接。从理论上来说,哈希连接的执行效率会比排序合并连接和嵌套循环连接要高,当然,实际情况并不总是这样。

对于哈希连接的优缺点及适用场景,我们有如下总结。

  • 哈希连接不一定会排序,或者说大多数情况下都不需要排序。
  • 哈希连接的驱动表所对应的连接列的可选择性应尽可能好,因为这个可选择性会影响对应 Hash Bucket中的记录数,而 Hash Bucket 中的记录数又会直接影响从该 Hash Bucket 中查找匹配记录的效率。如果一个Hash Bucket 里所包含的记录数过多,则可能会严重降低所对应哈希连接的执行效率,此时典型的表现就是该哈希连接执行了很长时间都没有结束,数据库所在数据库服务器上的 CPU占用率很高但目标SQL所消耗的逻辑读却很低,因为此时大部分时间都耗费在了遍历上述 Hash Bucket 里的所有记录上,而遍历 Hash Bucket 里的记录这个动作发生在 PGA的工作区里,所以不耗费逻辑读
  • 哈希连接只适用于CBO,它也只能用于等值连接条件(即使是哈希反连接,Oracle 实际上也是将其转换成了等价的等值连接)。
  • 哈希连接很适合于小表和大表之间做表连接且连接结果集的记录数较多的情形,特别是在小表的连接列的可选择性非常好的情况下,这时候哈希连接的执行时间就可以近似看作是和全表扫描那个大表所耗费的时间相当。
  • 当两个表做哈希连接时,如果在施加了目标 SOL 中指定的谓词条件(如果有的话)后得到的数据量较小的那个结果集所对应的 Hash Table 能够完全被容纳在内存中(PGA 的工作区),则此时的哈希连接的执行效率会非常高。

3.访问单表的方法

对于优化器而言,仅决定表连接顺序和表连接方法是不够的,这还不足以得到目标 SQL 的最终执行计划,因为优化器在对目标 SOL 中的各个表两两做表连接时,还必须决定如何去获取存储在这些表里的不同维度的数据,即优化器还要决定访问单表的方法。比如在访问某个单表时,是采用全表扫描还是走索引,如果是走索引,应该采用什么样的索引访问方法等(见上一篇笔记)。

4.表连接的类型

通常情况下,我们可以认为 Oracle 数据库中的表连接分为内连接和外连接这两种类型,表连接的类型会直接决定表连接的结果,而目标SOL的SOL文本的写法又直接决定了表连接的类型。

内连接(Inmer Join)是指表连接的连接结果只包含那些完全满足连接条件的记录。对于包含表连接的目标SQL而言,只要其 where条件中没有写那些标准 SQL中定义或者 Oracle 中自定义的表示外连接的关键字(比如标准 SOL 中的 left outer join、right outer join 、full outer join,或者 Oracle 中自定义的用来表示外连接的关键字“(+)”),则该SQL 的连接类型就是内连接。

外连接(Outer Join)是对内连接的一种扩展,它是指表连接的连接结果除了包含那些完全满足连接条件的记录之外还会包含驱动表中所有不满足该连接条件的记录。
标准SQL 中的外连接分为左连接(Left Outer Join)右连接(Right uter Join)和全连接(Full uter Join)这三种,它们在标准 SOL中所对应的关键字分别为 left outer joinright outer join 和 full outer join,都可以和JOINON或JOINUSING 连用。

你可能感兴趣的:(oracle,笔记,数据库)