使用 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 网站上更好,请告诉我...)
这很容易解释:只有当连接条件使用相等运算符 (
=
) 时,散列和合并连接才是可能的。由于您的连接条件基于函数结果 (st_equals(p2.geom, p1.geom)
),因此 PostgreSQL 无法使用这些连接算法中的任何一种,而必须求助于嵌套循环连接。顺便说一下,st_equals()
与 =
有很大不同。
在连接的情况下,postgres 出于以下原因切换到嵌套连接: