IT技术博客大学习 共学习 共进步

Oracle hash join

Alibaba DBA Team 2010-11-28 18:56:00 浏览 4,123 次

    hash join是oracle里面一个非常强悍的功能,当做hash join时,oracle会选择一个表作为驱动表,先根据过滤条件排除不必要的数据,然后将结果集做成hash表,放入进程的hash area,接着扫描第二张表,将行的键值做hash运算,到内存的hash表里面去探测,如果探测成功,就返回数据,否则这行就丢弃掉这个是最基本的解释,实际情况中,考虑到单个进程PGA的大小,oracle不会让进程任意的消耗OS内存,hash area是有一定限制的,所以在oracle中,hash也有三种模式:

    optimal,onepass,multipass

    optimal:当驱动结果集生成的hash表全部可以放入PGA的hash area时,称为optimal,大致过程如下:

    1.先根据驱动表,得到驱动结果集

    2.在hash area生成hash bulket,并将若干bulket分成一组,成为一个partition,还会生成一个bitmap的列表,每个bulket在上面占一位

    3.对结果集的join键做hash运算,将数据分散到相应partition的bulket中,当运算完成后,如果键值唯一性较高的话,bulket里的数据会比较均匀,也有可能有的桶里面数据会是空的,这样bitmap上对应的标志位就是0,有数据的桶,标志位会是1

    4.开始扫描第二张表,对jion键做hash运算,确定应该到某个partition的某个bulket去探测,探测之前,会看这个bulket的bitmap是否会1,如果为0,表示没数据,这行就直接丢弃掉

    5.如果bitmap为1,则在桶内做精确匹配,判断OK后,返回数据

    这个是最优的hash join,他的成本基本是两张表的full table scan,在加微量的hash运算

    onepass

    如果进程的pga很小,或者驱动表结果集很大,超过了hash area的大小,会怎么办?当然会用到临时表空间,此时oracle的处理方式稍微复杂点需奥注意上面提到的有个partition的概念,可以这么理解,数据是经过两次hash运算的,先确定你的partition,再确定你的bulket,假设hash area小于整个hash table,但至少大于一个partition的size,这个时候走的就是onepass

    当我们生成好hash表后,状况是部分partition留在内存中,其他的partition留在磁盘临时表空间中,当然也有可能某个partition一半在内存,一半在磁盘,剩下的步骤大致如下:

    1.扫描第二张表,对join键做hash运算,确定好对应的partition和bulket

    2.查看bitmap,确定bulket是否有数据,没有则直接丢弃

    3.如果有数据,并且这个partition是在内存中的,就进入对应的桶去精确匹配,能匹配上,就返回这行数据,否则丢弃

    4.如果partition是在磁盘上的,则将这行数据放入磁盘中暂存起来,保存的形式也是partition,bulket的方式

    5.当第二张表被扫描完后,剩下的是驱动表和探测表生成的一大堆partition,保留在磁盘上

    6.由于两边的数据都按照相同的hash算法做了partition和bulket,现在只要成对的比较两边partition数据即可,并且在比较的时候,oracle也做了优化处理,没有严格的驱动与被驱动关系,他会在partition对中选较小的一个作为驱动来进行,直到磁盘上所有的partition对都join完

    可以发现,相比optimal,他多出的成本是对于无法放入内存的partition,重新读取了一次,所以称为onepass,只要你的内存保证能装下一个partition,oracle都会腾挪空间,每个磁盘partition做到onepass

    multipass

    这是最复杂,最糟糕的hash join,此时hash area小到连一个partition也容纳不下,当扫描好驱动表后,可能只有半个partition留在hash area中,另半个加其他的partition全在磁盘上,剩下的步骤和onepass比价类似,不同的是针对partition的处理

    由于驱动表只有半个partition在内存中,探测表对应的partition数据做探测时,如果匹配不上,这行还不能直接丢弃,需要继续保留到磁盘,和驱动表剩下的半个partition再做join,这里举例的是内存可以装下半个partition,如果装的更少的话,反复join的次数将更多,当发生multipass时,partition物理读的次数会显著增加。

建议继续学习

  1. HashMap解决hash冲突的方法 (阅读 12,463)
  2. 关于memcache分布式一致性hash (阅读 11,661)
  3. MinHash原理与应用 (阅读 6,922)
  4. HBase二级索引与Join (阅读 6,861)
  5. SQL里是否可以使用JOIN (阅读 6,664)
  6. 无锁HashMap的原理与实现 (阅读 6,582)
  7. LVS hash size解决4096个并发的问题 (阅读 6,282)
  8. 如果用户在5分钟内重复上线,就给他发警告,问如何设计? (阅读 5,883)
  9. Ubuntu 下Hash校验和不符问题的解决 (阅读 5,463)
  10. 分布式系统hash策略 (阅读 5,124)