文章目录

  • Oracle join算法
  • 一、排序合并连接(SMJ)
  • 二、嵌套循环(NL)
  • 三、哈希连接(HJ)


Oracle join算法

在Oracle中,连接算法分为以下三类

• 排序合并连接(Sort Merge Join,简称SMJ)

• 嵌套循环(Nested Loops Join,简称NL)

• 哈希连接(Hash Join,简称HJ)

一、排序合并连接(SMJ)

如果连接属性上都建有索引,那么可利用索引已有的排序作合并连接。但如果在连接属性上没有索引时,那么需要首先对两表在连接属性上排序,对排序结果再作连接。 通常情况下,哈希连接的效果都比排序合并连接要好,然而如果行源已经被排过序,那么在执行排序合并连接时不需要再排序了,在这种情况下排序合并连接的性能会优于哈希连接。可以使用USEMERGE(T1 T2)来强制使用排序合并连接。 *如果相关联的表都是一个数量级,且其中一个或多个表在关联字段上有索引,那么此时使用该提示将可获得比其它两种JOIN方式更好的性能。需要注意的是,如果相关联的表是同一数量级,且相关联的表在关联字段上没有索引,那么该种方式下系统将会对所关联的表都进行全表扫描排序,其成本极高。所以,在有的数据库系统中,已不使用SMJ的关联方式,取而代之的是使用HJ*的方式。 在Oracle**数据库中有一个隐含参数“OPTIMIZERSORTMERGEJOIN_ENABLED”控制着SMJ的启用和关闭,该参数默认值是TRUE,表示启用SMJ连接。

二、嵌套循环(NL)

NL是一种比较高效的连接方式,内部表循环与外部表相匹配。这个连接方法有驱动表(外部表)的概念,该连接过程是一个2层嵌套循环。 在嵌套循环连接中,Oracle读取驱动表(外部表)中的每一行,然后在被驱动表(内部表)中检查是否有匹配的行,所有被匹配的行都被放到结果集中,然后处理驱动表中的下一行。这个过程一直继续,直到驱动表中的所有行都被处理。这是从连接操作中可以得到第一个匹配行的最快的方法之一,这种类型的连接可以用在需要快速响应的语句中。 嵌套循环连接可以先返回已经连接的行,而不必等待所有的连接操作处理完才返回数据,这可以获取快速的响应。嵌套循环连接适用于大表和小表的关联,一般小表作为驱动表。

三、哈希连接(HJ)

HJ的连接原理如下:首先把小表的哈希操作存放到内存中,然后用大表的每条记录做哈希,与之前小表的哈希值匹配。这种连接是在Oracle 7.3引入的,从理论上来说比NL与SMJ更高效,而且只用在CBO(Cost Based Optimization,基于代价的优化器)优化器中。

哈希连接的连接过程如下所示:

• 构建阶段:优化器首先选择一张小表作为驱动表,运用哈希函数对连接列进行计算产生一张哈希表。通常这个步骤是在内存(HASHAREASIZE)中进行的,所以,运算很快。

• 探测阶段:优化器对被驱动表的连接列运用同样的哈希函数计算得到的结果与前面形成的哈希表进行探测返回符合条件的记录。这个阶段中如果被驱动表的连接列的值没有与驱动表连接列的值相等的话,那么这些记录将会被丢弃而不进行探测。

这种方式适用于较小的表完全可以放于内存中的情况,这样总成本就是访问两个表的成本之和。在表很大的情况下并不能完全放入内存,这时优化器会将它分割成若干不同的分区,不能放入内存的部分就把该分区写入磁盘的临时段,此时要有较大的临时段从而尽量提高I/O的性能。HJ也适用于两个大表的关联。

哈希连接也可以用USE HASH(T1 T2)提示来强制使用。如果使用哈希连接,那么初始化参数HASHAREASIZE必须足够的大,如果是Oracle 9i以上版本,那么Oracle建议使用SQL工作区自动管理,设置WORKAREASIZEPOLICY为AUTO,然后调整PGA*AGGREGATE_TARGET的大小即可。

在Oracle数据库中有一个隐含参数“HASHJOIN_ENABLED”控制着HJ的启用和关闭,该参数默认值是TRUE,表示启用HJ连接。