让我们考虑以下查询:
EXPLAIN (ANALYZE, BUFFERS) SELECT * FROM foo JOIN bar ON foo.c1=bar.c1;
在哪里
CREATE TABLE foo
(
c1 integer,
c2 text
)
和
CREATE TABLE bar
(
c1 integer,
c2 boolean
)
如本 article 中所述
PostgreSQL does a sequential scan of table bar, and computes the hash for each of its rows. Then, it does a sequential scan of foo, and for each row, computes the hash of the row and compares it to the bar hashed table. If it matches, the row will be put in the resulting set. If it doesn't match, the row is skipped.
计划如下:
Hash Join (cost=13463.00..49297.00 rows=500000 width=42) (actual time=95.634..1001.306 rows=500000 loops=1)
Hash Cond: (foo.c1 = bar.c1)
Buffers: shared hit=3850 read=6697
-> Seq Scan on foo (cost=0.00..18334.00 rows=1000000 width=37) (actual time=0.026..135.609 rows=1000000 loops=1)
Buffers: shared hit=1637 read=6697
-> Hash (cost=7213.00..7213.00 rows=500000 width=5) (actual time=95.478..95.478 rows=500000 loops=1)
Buckets: 65536 Batches: 1 Memory Usage: 18067kB
Buffers: shared hit=2213
-> Seq Scan on bar (cost=0.00..7213.00 rows=500000 width=5) (actual time=0.004..37.040 rows=500000 loops=1)
Buffers: shared hit=2213
Total runtime: 1017.572 ms
我无法理解的是如何确定该行是否应该在结果集中。哈希值相等的事实并不意味着行满足谓词 foo.c1=bar.c1
。
问题: 那么,在比较哈希之后,我们应该检查谓词是否满足?另外,是否每个桶都包含具有相同散列的行?
最佳答案
- 那么,在比较哈希之后,我们应该检查谓词是否满足?
是的。
哈希连接使用连接属性作为哈希键。当两行的散列函数值相等时,我们必须 (a) 检查连接属性实际上是否相等,以及 (b) 检查是否也满足其他连接条件。
在您的示例中,连接属性是 foo.c1
和 bar.c1
,并且没有其他连接条件。
更复杂的示例:SELECT * FROM foo JOIN bar ON foo.c1 = bar.c1 AND foo.c1 > bar.c1;
。在这种情况下,我们仍然可以在 =
运算符上使用散列连接,但还必须检查 foo.c1 > bar.c1
。
如果您对细节感兴趣,请查看源代码(以 nodeHashjoin.c 开头)。
- 每个桶是否必须包含具有相同散列的行?
根据定义它是正确的,不是吗?哈希函数将键映射到哈希表中的索引,即。 e.到桶数字。
但严格来说,不是具有相同散列的行,而是连接具有相同散列的属性。
关于sql - 理解 postgreSQL 中的 HashJoin,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33018683/