【问题标题】:Understanding HashJoin in postgreSQL了解 postgreSQL 中的 HashJoin
【发布时间】:2015-10-08 14:28:58
【问题描述】:

让我们考虑以下查询:

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 对表 bar 进行顺序扫描,并计算哈希 对于它的每一行。然后,它对 foo 进行顺序扫描,并为 每行,计算行的哈希值并将其与条形图进行比较 哈希表。 如果匹配,该行将被放入结果中 设置。如果不匹配,则跳过该行。

计划如下:

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

问题: 那么,在比较哈希之后,我们应该检查谓词是否满足?另外,每个桶是否必须包含具有相同哈希的行?

【问题讨论】:

标签: sql postgresql join hash


【解决方案1】:
  1. 那么,在比较哈希之后,我们应该检查谓词是否满足?

是的。

哈希连接使用连接属性作为哈希键。当两行的哈希函数值相等时,我们必须(a)检查连接属性是否实际上相等,并且(b)检查其他连接条件是否也满足。

在您的示例中,连接属性是 foo.c1bar.c1,并且没有其他连接条件。

更复杂的例子:SELECT * FROM foo JOIN bar ON foo.c1 = bar.c1 AND foo.c1 > bar.c1;。在这种情况下,我们仍然可以在= 运算符上使用哈希连接,但还必须检查foo.c1 > bar.c1

如果您对细节感兴趣,请查看源代码(以nodeHashjoin.c 开头)。


  1. 每个桶是否必须包含具有相同哈希的行?

根据定义,这是真的,不是吗?哈希函数将键映射到哈希表中的索引,即。 e.存储桶数。

但严格来说,不是具有相同hash的行,而是加入具有相同hash的属性

【讨论】:

  • 非常感谢您的回答,尤其是对源代码的引用。但我可以再问你一个问题。据我从您的回答中得知,我们有一个包含 attributes 的哈希表,在我们的例子中就是 foo.c1(表 foo 的哈希表)。但是如果我们有更复杂的,比如Hash Cond: ((foo.c1 = baz.c1) AND (foo.c2 = baz.c2))。在这种情况下,foohashtable 是否会包含 (foo.c1, foo.c2) 的元组?
  • 在某种程度上,是的。虽然我不确定实施细节。源代码就是答案...
【解决方案2】:

报价具有误导性。它不是“行的散列”,而是“与行关联的散列值”。不是整行被散列,只有部分被散列。更具体地说:只有出现在连接的 ON 子句中的列的值才会被散列。当然,现在在两个表中寻找匹配的哈希值正是连接操作需要做的事情。

是的,显然必须检查这些散列值是否实际上相等,因为散列冲突是可能的。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-01-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-10-09
    • 2023-03-12
    相关资源
    最近更新 更多