让我们考虑以下查询:
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
)正如本文章所解释的那样
PostgreSQL对表格栏进行顺序扫描,并计算其每一行的哈希值。然后,它对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。
问题:那么,在比较散列之后,我们应该检查谓词是否满足?另外,每个桶都包含具有相同哈希的行,这是必要的吗?
发布于 2015-10-08 20:22:33
是。
散列联接使用联接属性作为散列键。当两行的哈希函数值相等时,我们必须(a)检查join属性实际上是否相等,(b)检查其他join限定条件是否也满足。
在您的示例中,join属性是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开始)。
从定义上来说,这是真的,不是吗?哈希函数将键映射到哈希表中的索引,即桶号。
但是严格地说,不是具有相同哈希的行,而是用相同的哈希连接属性。
发布于 2015-10-08 14:48:25
这句话有误导性。它不是“行的哈希”,而是“与行关联的哈希值”。不是整个行正在被散列,而是其中的一些部分被散列。更具体地说,只有来自于联接的ON子句中的列的值才会被散列化。现在,当然,在两个表中寻找匹配的散列是连接操作所需要的。
是的,很明显,我们必须检查那些哈希值实际上是否相等,因为哈希冲突是可能的。
https://stackoverflow.com/questions/33018683
复制相似问题