文章结束给大家来个程序员笑话:[M]
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念概
[color=ize:24px]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道理
[color=ize:24px]斟酌以下两个据数集:
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
hash_multiblock_io_count是个隐藏参数,在9.0.1当前就不再用使了
sys@ORCL> ed
Wrote file afiedt.buf
1 select a.ksppinm name,b.ksppstvl value,a.ksppdesc description
2 from x$ksppi a,x$ksppcv b
3 where a.indx = b.indx
4* and a.ksppinm like '%hash_multiblock_io_count%'
sys@ORCL> /
NAME VALUE DESCRIPTION
------------------------------ ----- ------------------------------------------------------------
_hash_multiblock_io_count 0 number of blocks hash join will read/write at once
Oracle用采外部一个hash函数作用于接连键上,将S和B分割成多个分区
在这里我们假设这个hash函数为求余函数,即Mod(join_column_value,10)
这样生产十个分区,如下表:
经过这样的分区以后,只须要响应的分区之间做join可即(也就是所谓的partition pairs)
如果有一个分区为NULL的话,则响应的分区join可即略忽
在将S表读入内存分区时,oracle即记载接连键的独一值,构建成所谓的位图向量
它须要占hash area内存的5%右左。在这里即为{1,3,4,5,8,10}
当对B表停止分区时,将个一每接连键上的值与位图向量相较比,如果不在其中,则将其记载弃丢
在我们这个例子中,B表中以下据数将被弃丢{0,0,2,2,2,2,2,2,9,9,9,9,9}
这个程过就是位图向量过滤
当S1,B1做完接连后,接着对Si,Bi停止接连
这里oracle将较比两个分区,选取小的那个做build input,就是态动角色换互
这个态动角色换互产生在除第一对分区之外的分区面上
㈢ Hash Join算法
[color=ize:24px]第1步:判断小表否是够能全体放存在hash area内存中,如果可以,则做内存hash join。如果行不,转第二步
第2步:决议fan-out数
(Number of Partitions) * C<= Favm *M
其中C为Cluster size,其值为DB_BLOCK_SIZE*HASH_MULTIBLOCK_IO_COUNT
Favm为hash area内存可以用使的百分比,一般为0.8右左
M为Hash_area_size的巨细
第3步:读取分部小表S,用采外部hash函数(这里称为hash_fun_1)
将接连键值映射至某个分区,同时用采hash_fun_2函数对接连键值生产另外一个hash值
这个hash值用于创立hash table用,并且与接连键值放存在起一
第4步:对build input立建位图向量
第5步:如果内存中没有空间了,则将分区写至磁盘上
第6步:读取小表S的残余分部,重复第三步,直至小表S全体读完
第7步:将分区按巨细排序,选取几个分区立建hash table(这里选取分区的原则是使选取的数量最多)
第8步:根据面前用hash_fun_2函数算计好的hash值,立建hash table
第9步:读取表B,用采位图向量停止位图向量过滤
第10步:对通过过滤的据数用采hash_fun_1函数将据数映射到响应的分区中去,并算计hash_fun_2的hash值
第11步:如果所落的分区在内存中,则将面前通过hash_fun_2函数算计所得的hash值与内存中已存在的hash table做接连
将结果写致磁盘上。如果所落的分区不在内存中,则将响应的值与表S响应的分区放在起一
第12步:续继读取表B,重复第9步,直至表B读取终了
第13步:读取响应的(Si,Bi)做hash接连。在这里会产生态动角色换互
第14步:如果分区后过,小最的分区也比内存大,则产生nested-loop hash join
㈣ Hash Join的本成
⑴ In-Memory Hash Join
Cost(HJ)=Read(S)+ build hash table in memory(CPU)+Read(B) + Perform In memory Join(CPU)
略忽cpu的时光,则:
Cost(HJ)=Read(S)+Read(B)
⑵ On-Disk Hash Join
根据上述的骤步述描,我们可以看出:
Cost(HJ)=Cost(HJ1)+Cost(HJ2)
其中Cost(HJ1)的本成就是扫描S,B表,并将没法放在内存上的分部写回磁盘,对应面前第2步至第12步
Cost(HJ2)即为做nested-loop hash join的本成,对应面前的第13步至第14步
其中Cost(HJ1)近似于等Read(S)+Read(B)+Write((S-M)+(B-B*M/S))
因为在做nested-loop hash join时,对每一chunk的build input,都须要读取整个probe input,因此
Cost(HJ2)近似于等Read((S-M)+n*(B-B*M/S)),其中n是nested-loop hash join须要循环的次数:n=(S/F)/M
一般情况下,如果n大于10的话,hash join的能性将大大下落
从n的算计公式可以看出,n与Fan-out成反比例,高提fan-out,可以低降n
当hash_area_size是固准时,可以低降cluster size来高提fan-out
从这里我们可以看出,高提hash_multiblock_io_count参数的值并不一定高提hash join的能性
㈤ Hash Join的程过
[color=ize:24px]一次完全的hash join如下:
1 算计小表的分区(bucket)数--Hash分桶
决议hash join的一个重要因素是小表的分区(bucket)数
这个字数由hash_area_size、hash_multiblock_io_count和db_block_size参数独特决议
Oracle会留保hash
游戏开辟论坛:http://jiushun8.com/forum.php?mod=viewthread&tid=5546&extra=page%3D1
文章结束给大家分享下程序员的一些笑话语录: 手机终究会变成PC,所以ip会比wm更加畅销,但是有一天手机强大到一定程度了就会发现只有wm的支持才能完美享受。就好比树和草,草长得再高也是草,时间到了条件成熟了树就会窜天高了。www.ishuo.cn