深入理解Oracle表(5):三大表连接方式详解之Hash Join的定义,原理,算法,成本,模式和位图

       Hash Join只能用于相等连接,且只能在CBO优化器模式下。相对于nested loop join,hash join更适合处理大型结果集
       Hash Join的执行计划第1个是hash表(build table),第2个探查表(probe table),一般不叫内外表,nested loop才有内外表
       Hash表也就是所谓的内表,探查表所谓的外表
       两者的执行计划形如:
       nested loop
           outer table             --驱动表
           inner table
       
       hash join
          build table              (inner table) --驱动表

          probe table             (outer  table) 

       先看一张图片,大致了解Hash Join的过程:

      

       下面详细了解一下Hash Join

       ㈠ Hash join概念
          
          Hash join算法的一个基本思想就是根据小的row sources(称作build input 也就是前文提到的build table,我们记较小的表为S,较大的表为B)
          建立一个可以存在于hash area内存中的hash table
          然后用大的row sources(称作probe input,也就是前文提到的probe table) 来探测前面所建的hash table
          如果hash area内存不够大,hash table就无法完全存放在hash area内存中
          针对这种情况,Oracle在连接键利用一个hash函数将build input和probe input分割成多个不相连的分区
          分别记作Si和Bi,这个阶段叫做分区阶段;然后各自相应的分区,即Si和Bi再做Hash join,这个阶段叫做join阶段 
          如果HASH表太大,无法一次构造在内存中,则分成若干个partition,写入磁盘的temporary segment,则会多一个写的代价,会降低效率
          至于小表的概念,对于 hash join 来说,能容纳在 pga 中的 hash table 都可以叫小表,通常比如:
          pga_aggregate_target                 big integer    1073741824
          hash  area size 大体能使用到40多 M ,这样的话通常可能容纳 几十万的记录
          hash area size缺省是2*sort_area_size,我们可以直接修改SORT_AREA_SIZE 的大小,HASH_AREA_SIZE也会跟着改变的
          如果你的workarea_size_policy=auto,那么我们只需设定pga_aggregate_target
          但请记住,这是一个session级别的参数,有时,我们更倾向于把hash_area_size的大小设成驱动表的1.6倍左右
          驱动表仅仅用于nested loop join 和 hash join,但Hash join不需要在驱动表上存在索引,而nested loop join则迫切需求
          一两百万记录的表 join上  千万记录的表,hash join的通常表现非常好
          不过,多与少,大与小,很多时候很难量化,具体情况还得具体分析
          如果在分区后,针对某个分区所建的hash table还是太大的话,oracle就采用nested loop hash join
          所谓的nested-loops hash join就是对部分Si建立hash table,然后读取所有的Bi与所建的hash table做连接
          然后再对剩余的Si建立hash table,再将所有的Bi与所建的hash table做连接,直至所有的Si都连接完了
       
       ㈡ Hash Join原理
       
          虑以下两个数据集:
          S={1,1,1,3,3,4,4,4,4,5,8,8,8,8,10}
          B={0,0,1,1,1,1,2,2,2,2,2,2,3,8,9,9,9,10,10,11}
          Hash Join的第一步就是判定小表(即build input)是否能完全存放在hash area内存中
          如果能完全存放在内存中,则在内存中建立hash table,这是最简单的hash join
          如果不能全部存放在内存中,则build input必须分区。分区的个数叫做fan-out
          Fan-out是由hash_area_size和cluster size来决定的。其中cluster size等于db_block_size * _hash_multiblock_io_count
       

  • 7
    点赞
  • 40
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Oracle中的Hash Join是一种基于哈希连接算法,它通常用于处理大型数据集上的连接操作。它的基本原理是将连接的两个数据集分别通过哈希函数映射到不同的哈希中,并在哈希中查找匹配的行,最终将匹配的行合并为结果集。 具体来说,Hash Join算法分为两个阶段: 1. 构建哈希:首先,将连接的左(较小的数据集)通过哈希函数计算出哈希值,然后将每一行插入到哈希中对应的桶中。这个过程称为“构建哈希”。 2. 执行连接操作:接下来,将连接的右(较大的数据集)的每一行也通过哈希函数计算出哈希值,然后在左的哈希中查找是否有匹配的行。如果找到了匹配的行,就将它们合并为一条结果行输出。 可以看出,Hash Join 算法的性能取决于哈希的构建和查找速度。当哈希足够小,可以全部缓存在内存中时,Hash Join 算法的性能是非常高的。但如果哈希太大,无法全部缓存在内存中,那么就会产生大量的磁盘I/O操作,从而严重影响性能。 下面是一个简单的案例,假设我们有两个A和B,它们的结构如下: A: ``` id name 1 Alice 2 Bob 3 Charlie 4 David ``` B: ``` id age 1 20 2 25 3 30 ``` 现在我们要将这两个按照id进行连接。使用Hash Join算法,具体的执行步骤如下: 1. 构建哈希:首先,将A中的每一行都通过哈希函数计算出哈希值,并插入到哈希中对应的桶中。这个过程如下: ``` Bucket 1: {1, Alice} Bucket 2: {2, Bob} Bucket 3: {3, Charlie} Bucket 4: {4, David} ``` 2. 执行连接操作:接下来,遍历B中的每一行,也通过哈希函数计算出哈希值,并在A的哈希中查找是否有匹配的行。具体的查找过程如下: ``` Row {1, 20}: 查找Bucket 1,找到匹配的行{1, Alice},将它们合并为结果行{1, Alice, 20} Row {2, 25}: 查找Bucket 2,找到匹配的行{2, Bob},将它们合并为结果行{2, Bob, 25} Row {3, 30}: 查找Bucket 3,找到匹配的行{3, Charlie},将它们合并为结果行{3, Charlie, 30} ``` 最终,Hash Join算法输出的结果集如下: ``` id name age 1 Alice 20 2 Bob 25 3 Charlie 30 ``` 可以看出,Hash Join算法非常适合处理大型数据集上的连接操作,它的性能比其他连接算法如Nested Loop Join和Merge Join都要高效。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值