postgresql源码(十四)——Executor(查询执行模块之——Join节点(下))

本文详细介绍了PostgreSQL中HashJoin节点的工作原理,包括Hash连接算法步骤、Hash表管理、多线程内连接优化,以及状态机在执行流程中的应用。重点讨论了分块与分桶策略,以及如何通过内存管理提高连接效率。

3.HashJoin 节点

postgres=# explain select a.*,b.* from test_dm a join test_dm2 b on a.xxx = b.xxx;
                                   QUERY PLAN
--------------------------------------------------------------------------------
 Hash Join  (cost=34846.00..305803.23 rows=1000000 width=137)
   Hash Cond: ((b.xxx)::text = (a.xxx)::text)
   ->  Seq Scan on test_dm2 b  (cost=0.00..223457.17 rows=10000017 width=69)
   ->  Hash  (cost=22346.00..22346.00 rows=1000000 width=68)
         ->  Seq Scan on test_dm a  (cost=0.00..22346.00 rows=1000000 width=68)
(5 行)

Hashjoin节点实现了Hash连接算法,它能够实现前面说到的六种连接方式。

以下我们以表R(左关系)与表S(右关系)连接为例,说明Hash连接的实现过程。

1)对一个表(例如S)进行Hash时,其块和桶数量的确定和划分方法如下:

①首先对S分块(batch),估算存储S所占用的空间(inner_rel_bytes), Hash所使用的内存空间被定义为 1 兆(hash_table_bytes),则分块的数量 nbatch = ceil(inner_rel_bytes/hash_table_bytes)。

②在内存中,每一个块又被划分为大小为10个元组的桶,因此,个数为nbucket = (hash_table_bytes/tuplesize)/10,其中tuplesize为元组大小的估计值。

③对于一个Hash值为hashvalue的元组,其所属的分块号为(hashvalue/nbucket)%nbatch,其对应的桶号为hashvalue%nbucket。

④在PostgreSQL实现中,为了能够使用位操作(位与和移位)实现取模和取余操作,将nbatch和nbucket取为不小于计算值的2的n次,并使得2^log2_nbuckets = nbucket,则块号的计算方法为(hashvalue >> log2_nbuckets)&(nbatch - 1),桶号计算式为hashvalue&(nbucket - 1)。

2)执行HashJoin的算法:

①顺序获取S中的所有元组,对每一条元组进行Hash,并通过Hash结果获取块号和桶号。对于块号为0的元组,放人内存对应的桶内;否则放入为右关系每个块分别建立的临时文件中。此时,标记当前在内存中的块号curbatch为0。

②从R中获取元组,进行Hash,获取元组块号和桶号。当块号等于当前在内存中的块号时,直接扫描对应的桶,找寻满足条件的元组并进行连接;否则,将其存人为左关系每个块分别建立的临时文件中。执行过程,直到R被扫描完毕。

③从S的块号curbatch + 1对应的临时文件中读取所有存储的元组,将其Hash到相应的桶内,并将curbatch加1。

④从R的块号curbatch对应的临时文件中依次读取所存储的元组,计算其桶号,并扫描桶中S的元组,寻找满足连接条件的元组进行连接。

⑤重复步骤3和4,直到所有的块都被

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值