为啥我的基于 postgis ST_Intersects 和 ST_Azimuth 的查询很慢?
Posted
技术标签:
【中文标题】为啥我的基于 postgis ST_Intersects 和 ST_Azimuth 的查询很慢?【英文标题】:Why my postgis ST_Intersects and ST_Azimuth based query is slow?为什么我的基于 postgis ST_Intersects 和 ST_Azimuth 的查询很慢? 【发布时间】:2019-07-29 14:57:35 【问题描述】:我有一个表,其中包含大约 300k 条路线,起点、终点、路线为折线类型和多边形类型。
我做了一个自连接来找出路线的交叉点,但是查询很慢。即使我运行explain analyze
,这个分析也没有回报。
CREATE INDEX gist_index_geo_poly_gon ON geo_akin USING gist (geo_polygon)
CREATE INDEX gist_index_geo_poly_line ON geo_akin USING gist (geo_polyline)
CREATE INDEX idx_id ON geo_akin USING btree (id)
我有上面的索引,查询如下:
select
ST_Intersection(second.geo_polyline, first.geo_polygon) as intersection,
from geo_akin first
, geo_akin second
where second.id != first.id
and abs(sin(ST_Azimuth(second.actual_start_point, second.actual_end_point))- sin(ST_Azimuth(first.actual_start_point, first.actual_end_point)))<1
and abs(cos(ST_Azimuth(second.actual_start_point, second.actual_end_point))-cos(ST_Azimuth(first.actual_start_point, first.actual_end_point)))<1
and st_intersects(second.geo_polyline , first.geo_polygon);
下面是我的EXPLAIN
结果:
Nested Loop (cost=0.15..45452.35 rows=128519 width=64)
-> Seq Scan on geo_akin found (cost=0.00..2584.67 rows=3167 width=17077)
-> Index Scan using gist_index_geo_poly_line on geo_akin first (cost=0.15..2.97 rows=1 width=4244)
Index Cond: (geo_polyline && second.geo_polygon)
Filter: ((id <> second.id) AND (abs((sin(st_azimuth(actual_start_point, actual_end_point)) - sin(st_azimuth(second.actual_start_point, second.actual_end_point)))) < '1'::double precision) AND (abs((cos(st_azimuth(actual_start_point, actual_end_point)) - cos(st_azimuth(second.actual_start_point, second.actual_end_point)))) < '1'::double precision) AND _st_intersects(geo_polyline, second.geo_polygon))
【问题讨论】:
@a_horse_with_no_name 我已经添加了解释结果。 性能问题应该包括EXPLAIN
和一些关于表大小、索引、当前时间性能、期望时间等的信息。Slow
是一个相对术语,我们需要一个真实的值来比较。
为什么会有折线和多边形?或许你可以使用second.id > first.id
来避免反向比较?
谢谢@JuanCarlosOropeza 我错过了这一点。现在我添加这个条件来避免反向比较。因为其中之一是线路(路线)的集合,而其中之一只是一个区域。我想找到路口。
你的查询有多慢?你能提供一些例子吗?我在路线和多边形方面做了很多工作,如果了解问题所在,我可能会给你更好的建议
【参考方案1】:
我可以看到,您对 300k 表的自联接为您提供了 90.000 万个交叉点。我的建议是尝试将连接过滤为仅重叠的多边形,然后查找它们是否相交。
如果为边界多边形添加 X1、Y1、X2、Y2 并使用 (ID, X1, Y1, X2, Y2) 创建索引,您可以非常快速地找到重叠的多边形
SELECT ST_Intersection(b.geo_polyline, a.geo_polygon) AS intersection
FROM geo_akin a
JOIN geo_akin b
ON a.X1 <= b.X2
AND a.X2 >= b.X1
AND a.Y1 <= b.Y2
AND a.Y2 >= b.Y1
AND a.id < b.id
WHERE abs(sin(ST_Azimuth(b.actual_start_point, b.actual_end_point))
- sin(ST_Azimuth(a.actual_start_point, a.actual_end_point))) < 1
AND abs(cos(ST_Azimuth(b.actual_start_point, b.actual_end_point))
- cos(ST_Azimuth(a.actual_start_point, a.actual_end_point))) < 1
AND st_intersects(b.geo_polyline, a.geo_polygon);
【讨论】:
感谢回复,但是我们在where子句中已经有了st_intersects内置函数来查找是否有交集。您是否认为添加这些点并将它们作为条件会产生很大的不同? 是的,我想是的。如果不起作用,我们会尝试其他方法。以上是关于为啥我的基于 postgis ST_Intersects 和 ST_Azimuth 的查询很慢?的主要内容,如果未能解决你的问题,请参考以下文章