为什么Postgres优化器切换到嵌套循环进行连接?

问题描述 投票:0回答:2

使用 Postgres 和 Postgis,我使用

st_equals
遇到了非常慢的空间连接。出于好奇,我尝试使用
=
代替,连接速度更快。使用
EXPLAIN
,我注意到
st_equals
连接使用嵌套循环,而
=
使用哈希连接。

我远不是这里的专家 - 发生了什么事?我在这里找到了更快的选项,但有时我可能更喜欢使用

st_equals
并且让它速度更快...

就其价值而言,两个表中的

geom
列都是要点索引,并且 st_equals 利用了索引。两个表都有约 220K 行。

这是两个选择查询,后面是两个 EXPLAIN 结果。 (是的,我在一个表中找到了另一个表中不存在的记录,是的,我知道还有其他方法可以做到这一点,但现在让我们把它放在一边!)

A

explain
 select p1.geom from schema1.parcel p1
   join schema2.parcel p2
    on st_equals(p2.geom, p1.geom)
  where
    p2.pid is null

B

explain
 select p1.geom from schema1.parcel p1
   join schema2.parcel p2
     on p2.geom = p1.geom
  where
    p2.pid is null

解释一下

Gather  (cost=1000.42..2819605.27 rows=808 width=296)
  Workers Planned: 2
  ->  Nested Loop  (cost=0.42..2818524.47 rows=337 width=296)
        Join Filter: st_equals(p2.geom, p1.geom)
        ->  Parallel Seq Scan on parcel p1  (cost=0.00..9390.93 rows=95393 width=296)
        ->  Index Scan using parcel_pkey on parcel p2  (cost=0.42..4.44 rows=1 width=300)
              Index Cond: (pid IS NULL)

B 解释一下

Gather  (cost=1004.45..10776.96 rows=229 width=296)
  Workers Planned: 2
  ->  Hash Join  (cost=4.45..9754.06 rows=95 width=296)
        Hash Cond: (p1.geom = p2.geom)
        ->  Parallel Seq Scan on parcel p1  (cost=0.00..9390.93 rows=95393 width=296)
        ->  Hash  (cost=4.44..4.44 rows=1 width=300)
              ->  Index Scan using parcel_pkey on parcel p2  (cost=0.42..4.44 rows=1 width=300)
                    Index Cond: (pid IS NULL)

(如果这在 gis.stackexchange 网站上更好,请告诉我...)

postgresql performance query-optimization postgis
2个回答
0
投票

这很容易解释:只有当连接条件使用相等运算符 (

=
) 时,散列和合并连接才是可能的。由于您的连接条件基于函数结果 (
st_equals(p2.geom, p1.geom)
),因此 PostgreSQL 无法使用这些连接算法中的任何一种,而必须求助于嵌套循环连接。顺便说一下,
st_equals()
=
有很大不同。


0
投票

在连接的情况下,postgres 出于以下原因切换到嵌套连接:

  1. 连接表的一列/两列没有索引。
  2. 如果嵌套连接提供的结果比散列/合并连接更快。
  3. 有时,如果信息未更新,分析会提供错误的解释分析。
© www.soinside.com 2019 - 2024. All rights reserved.