1、sort merge join(SMJ) 排序-合并连接
连接过程:
将两个表排序,然后再进行join
①首先生产drving table【驱动表】需要的数据,然后对这些数据按照连接操作关联列进行排序;
②然后生产probed table【被探查表】需要的数据,然后对这些数据按照与driving table对应的连接操作列进行排序;
③最后两边已经排序的行被放在一起执行合并操作。
应用场景:
①排序是一个费时、费资源的操作,特别对于大表。所以SMJ通常不是一个特别有效的连接方法,但是如果driving table和probed table都已经预选排序,则这种连接方法的效率也比较高。
②对于非等值连接,这种连接方式的效率是比较高的;
③如果在关联的列上都有索引,效果更好;
④对于将2个较大的row source做连接,该连接方法比NL连接要好一些,但是如果sort merge返回的row source过大,则又会导致使用过多的rowid在表中查询数据时,因为过多的I/O,数据库性能下降。
2、nested loops(NL) 嵌套循环
连接过程:
连接过程就是将driving table【驱动表】和probed table【被探查表】进行一次嵌套循环的过程。就是用driving table【驱动表】的每一行去匹配probed table【被探查表】的所有行。nested loops有其他方法没有的一个优点:可以先进行返回已经连接的行,而不必等所有的连接操作处理完成才返回数据,这可以实现快速响应时间。
内部连接过程:
注:row source1:为驱动表或探查表或外部表;row source2:为被探查表或内部表
①row source1的row1-------probe------>row source2 所有行数据
②row source1的row2-------probe------>row source2 所有行数据
③row source1的row3-------probe------>row source2 所有行数据
…
row source1的rown-------probe------>row source2 所有行数据
应用场景:
如果driving row source【外部表】比较小(<10000条数据),并且在inner row table【内部表】上有唯一索引,或有高选择性非唯一索引时,使用这种方法可以得到较好的效率。
3、hash join 哈希连接
较小的row source被用来构建hash table与bitmap【位图索引】,第二个row source用来被hashed,并与第一个row source产生的hash table进行匹配。以便进行进一步的连接。当构建的hash table与bitmap能被容纳在内存中时,这种连接方式的效率极高。但是需要设置合适的hash_area_size参数且只能用于等值连接中。
注:hash 散列,哈希,就是把任意长度的输入,通过散列算法,变换成固定长度的输出,该输出就是散列值。应用于身份验证和数字签名,也成为“信息摘要”。
连接过程:
①将两表中较小的一个在内存中构造一个hash表(对join key 进行hash),扫描另一个表,同样对join key进行hash后探测是否可以join,找出与之匹配的行。
②一张小表被hash在内存中。因为数据量小,所以这张小表的大多数数据已经驻入在内存中,剩下的少量数据被放置在临时表空间中。
③每读取大表的一条记录,就和小表中内存中的数据进行比较,如果符合,则立即输出数据(也就是说没有读取临时表空间中的小表的数据)。而如果大表的数据与小表中临时表空间的数据相符,则不直接输出,而是也被存储在临时表空间中。
④当大表的所有数据都读取完毕,将临时表空间中的数据以其输出。如果小表的数据量足够小(小于hash_area_size),那所有数据就都在内存中了,可以避免对临时表空间的读写。
⑤如果是并行环境下,前面中的第2步就变成如下了:
每读取一条大表的记录和内存中小表的数据比较,如果符合先做join,而不直接输出,直到整张大表数据读取完毕。如果内存足够,join好的数据就保存在内存中。否则就保存在临时表空间中。
应用场景:
①这种方法是在oracle 7后来引入的,使用了比较先进的连接理论,一般来说,其效率应该好于其他2种连接,但是这种连接只能用在CBO优化器中,而且需要设置合适的hash_area_size参数,才能取得较好的性能;
②在2个较大的row source之间连接时会取得对应较好的效率,在一个row source较小时则能取得较好的效率。
③只能用于等值连接。