如果有两个表T1,T2,在做表连接时候使用的是哈希连接
oracle会执行以下步骤:
1、首先oralce会根据参数HASH_AREA_SIZE,DB_BLOCK_SIZE ,_HASH__MUTIBLOCK_IO_COUNT的值来决定HASH prtition的数量(HASH partition是一个逻辑上的概念,
它实际上是一组hash Buck的集合,所有的hash partition的集合就被乘坐HASH TABLE,即一个hash table由多个hash partition组成,而一个hash partition又是由多个
hash buckec组成)
2、表T1和T2会根据目标sql中所指定的谓词条件,得到的结果集中的数量较少的哪个结果集会被ORACLE被当做hash join的的驱动结果集,这里把T1的结果集S1当做驱动表,
T2的结果集S2当做被结果集
3、接着oracle会遍历结果集S,读取S中的每一条记录,并对每一条记录按照该记录在表T1中的连接列做哈希运算,这个哈希运算使用两个内置的哈希函数,这两个哈希函数
会计算出会分别得出hash_value1和hash_value2
4、然后oracle会按照HASH_VALUE1的值把相应的S1中对应记录存储在不同的HASH PARTITION的不同bucket里,同时和该记录存储在一起的还有该记录的HASH_VALUE2
存储在hash bucket里的记录并不是目标表完整行的记录,只需要存储于目标SQL中与目标表相关的查询列和连接列就章狗了,我们把S对应的每一个hash partition记录为S1a
5、在构建S1a的同时,oralce会构建一个位图,这个位图用来标记S1a所包含的每一个bucket是否有记录
6、如果S1的数据量很大,那么在构建S1所对应的HASH TABLE时,就可能会出现PGA工作区被填满的情况,这个时候oralce会把工作区所包含的记录数最多的HASH partition
写到磁盘上。接着oralce会继续构建S1所对应的hash table,在继续构建的过程中,如果工作区又满了,则oracle会继续重复把较大的hash partition写入磁盘。在极端情况下可能会出现只有某个hash partition的部分记录在内村中,该hash partition的剩余部分和余下所有的hash partition都已经被写回到磁盘上,这个过程会持续下去,直到便利完S1中所有的记录
7、接着oralce会对所有的S1a按照他们所包含记录数来排序,然后把这些已经排序号的hash partition按顺序依次且尽可能全部放到内存中,如果放不下,其他部分还会在磁盘上。
8、在oracle处理完S1时,开始处理S2,读取S2中的每一条记录,并按照记录在T2中的连接列做哈希运算,得出HASH_VLAUE3,HASH_VALUE4,结合ORACLE会按照
该记录所对应的哈希值HASH_VALUE3去S1a中查找匹配的HASH Bucket,如果能够找到匹配的HASH BUCKET,则oracle还会遍历该HASH Bucket中的每一天记录,
并教研存储于该hash bucket中的每一条记录的连接列,查看是否真的匹配,如果真的匹配,则HASH_VALUE1对应S2中记录的位于目标sql中的查询列就和该
HASH BACKET匹配记录组合起来,一起满足目标 sql连接条件的记录返回。
如果位图显示该hash bucket在s1中对应的记录数大于0,则说明hash bucket虽然不在内存中,但它已经被写回到磁盘,此时oracle就会按照HASH_VALUE1的值把相应
S2中对应记录也以hash partition的方式写回到磁盘上,同时记录的还有hash运算的第二个值S4,如果位图显示该HASH BUCKET在S1中对应的记录数等于0,则oracle就
无需把hash value3所对应S2中的记录写回磁盘,因为这条记录既然不满足目标sql的连接提哦啊见,这个根据位图来决定是否将HASH_VALUE1所对应S2中的记录写回
到磁盘的动作就是所谓的位图过滤,我们把S2所对应的每隔一HASH PARTITION记录为S2J,这种查找匹配记录会一直持续下去,知道遍历按完B中所有的记录
9、至此ORACLE已经处理完所有位于内存中S1A和对应的S2J,现在只剩下位于磁盘上的SI和BJ还未处理
10、oracle在处理位于磁盘上的S1A和S2J时候,只有对应hash partition number值相同的Si和Bj才可能产生满足条件的记录,磁盘上的匹配的记录用S1n和S2n记录
11、对于S1n和S2n,他们之中记录较少的会被当做驱动结果集,然后oracle会使用这个驱动结果集hash bucket里的记录hash_value2或者HASH_VALUE4来构建新的
hash table,另外一个记录数较多的会被当做被驱动结果集,对于每一个对S1n和S2n而言,oracle始终会选择他们中记录较少的作为驱动结果集,所以每一对sn的结
果集都会发生变化,这就是所谓的动态角色互换
12、这种匹配方式会一直延续下去,直到遍历完玩所有的S1n和S2n
哈希连接适用于:
1、哈希连接不一定会排序,或者说大多数的情况下都不需要排序
2、哈希连接的驱动表根据所对应的连接列的可选性尽量可能好,因为这个可选择性会影响对应hash bucket中的记录数,而hashhash bucket中的记录数又会直接影响从
该hash bucket中查找匹配记录的效率。如果一个hash bucket里所包含的记录数越多,则可能会降低所对应哈希连接的执行效率,此事典型的变现就是该哈希连接执行
了很长时间都没有结束,数据库所在数据库服务器上的CPU占用了率也很高,但目标sql所消耗的逻辑读却非常低,因为此事大部分时间都耗费在了便利上数的hash
bucket里所有的记录上,而便利hashbucket里的记录这个动作发生在PGA里,所以不耗费逻辑读。
3、哈希连接只适用于CBO,它也只能用于等值连接条件
4、哈希连接很适合小标和大表之间做表连接且连接结果集的记录数较多的情形,特别是在小标的连接列选择性非常好的情况下,这时候哈希连接的执行时间可以看做是
和全表扫描那个大表所耗费的时间。
5、当两个表做哈希连接时,如果在施加了目标SQL中制定了谓词条件后得到的数据量较小的那个结果集所对应的hash table能够完全被放在PGA中,此事哈希连接的
效果非常高。
可以借助10104事件所产生的trace文件来观察目标sql在做哈希连接时的一些统计信息
oradebug setmypid
oradebug event 10104 trace name context forever,level 1
set autotrace traceonly
A