Join是一种试图将两个表结合在一起的谓词,一次只能连接2个表,表连接也可以被称为表关联。有多种方法可以将2个表连接起来,当然每种方法都有自己的优缺点,每种连接类型只有在特定的条件下才会发挥出其最大优势。本文我们就来讲一讲4种Oracle表连接方式。

row source(表)之间的连接顺序对于查询的效率有非常大的影响。通过首先存取特定的表,即将该表作为驱动表,这样可以先应用某些限制条件,从而得到一个较小的row source,使连接的效率较高,这也就是我们常说的要先执行限制条件的原因。一般是在将表读入内存时,应用where子句中对该表的限制条件。

目前为止,无论连接操作符如何,典型的连接类型共有3种:

排序:合并连接(Sort Merge Join (SMJ) )、嵌套循环(Nested Loops (NL) )和哈希连接(Hash Join),另外,还有一种Cartesian product(笛卡尔积),一般情况下,尽量避免使用。下面我们来一一介绍这些4种Oracle表连接方式。

1、排序:合并连接(Sort Merge Join, SMJ)

内部连接过程:

(1)、首先生成row source1需要的数据,然后对这些数据按照连接操作关联列(如A.col3)进行排序。

(2)、 随后生成row source2需要的数据,然后对这些数据按照与sort source1对应的连接操作关联列(如B.col4)进行排序。

(3)、 最后两边已排序的行被放在一起执行合并操作,即将2个row source按照连接条件连接起来

排序是一个费时、费资源的操作,特别对于大表。基于这个原因,SMJ经常不是一个特别有效的连接方法,但是如果2个row source都已经预先排序,则这种连接方法的效率也是蛮高的。

2、嵌套循环(Nested Loops, NL)

这个连接方法有驱动表(外部表)的概念。其实,该连接过程就是一个2层嵌套循环,所以外层循环的次数越少越好,这也就是我们为什么将小表或返回较小 row source的表作为驱动表(用于外层循环)的理论依据。

3、哈希连接(Hash Join, HJ)

这种连接是在oracle 7.3以后引入的,从理论上来说比NL与SMJ更高效,而且只用在CBO优化器中。

较小的row source被用来构建hash table与bitmap,第2个row source被用来被hansed,并与第一个row source生成的hash table进行匹配,以便进行进一步的连接。Bitmap被用来作为一种比较快的查找方法,来检查在hash table中是否有匹配的行。

4、笛卡儿乘积(Cartesian Product)

当两个row source做连接,但是它们之间没有关联条件时,就会在两个row source中做笛卡儿乘积,这通常由编写代码疏漏造成(即程序员忘了写关联条件)。笛卡尔乘积是一个表的每一行依次与另一个表中的所有行匹配。在特殊情况下我们可以使用笛卡儿乘积,如在星形连接中,除此之外,我们要尽量不使用笛卡儿乘积。

不同情况下我们采用的Oracle表连接方式也是不同的,对于非等值连接,排序——合并连接的方式效率是比较高的,而哈希连接只能用于等值连接中。如果外部表比较小,并且在内部表上有唯一索引,或有高选择性非唯一索引时,选择嵌套循环。

最后修改:2021 年 10 月 06 日
如果觉得我的文章对你有用,请随意赞赏