为什么我的Postgis ST_Intersects和基于ST_Azimuth的查询速度慢?

时间:2019-07-29 14:57:35

标签: sql postgresql performance postgis

我有一个表,其中包含约30万条路线,起点,终点,路线为折线类型和面类型。

我进行了自我连接,以找出路线之间的交叉点,但查询速度很慢。即使我运行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))

1 个答案:

答案 0 :(得分:0)

enter image description here

我能看到的是您的300k表格的自我连接为您提供了900亿个交点。我的建议是尝试将连接过滤为仅重叠的多边形,然后查找它们是否相交。

如果为边界多边形添加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);