【问题标题】:Assign points to polygons effeciently有效地将点分配给多边形
【发布时间】:2019-03-25 09:45:18
【问题描述】:

我有多边形表(千)和点表(百万)。两个表在几何列上都有 GIST 索引。重要的是,多边形不会重叠,因此每个点都包含在一个多边形中。我想用这个关系(polygon_id + point_id)生成表。

简单的解决方案当然是

SELECT a.polygon_id, p.point_id
FROM my_polygons a
JOIN my_points p ON ST_Contains(a.geom, p.geom)

这行得通,但我认为它不必要的慢,因为它匹配每个多边形与每个点 - 它不知道每个点只能属于一个多边形。

有什么办法可以加快速度吗?

我尝试对每个多边形进行循环,通过 ST_Contains 选择点,但只选择那些尚未在结果表中的点:

CREATE TABLE polygon2point (polygon_id uuid, point_id uuid);

DO $$DECLARE r record;
BEGIN
    FOR r IN SELECT polygon_id, geom
         FROM my_polygon             
    LOOP

    INSERT INTO polygon2point (polygon_id, point_id) 
    SELECT r.polygon_id, p.point_id
    FROM my_points p
    LEFT JOIN polygon2point t ON p.point_id = t.point_id
    WHERE t.point_id IS NULL AND ST_Contains(r.geom, p.geom);

    END LOOP;
END$$;

这甚至比普通的 JOIN 方法还要慢。有什么想法吗?

【问题讨论】:

  • 我不知道 postgis,所以你能澄清一下:当你调用 ST_Contains 时,my_points 上是否使用了索引?什么是“不必要的慢”,你能给我们实际的时间吗?而且只有数千个(多少个?)多边形,每个多边形只包含点表中的一个点(我假设只是一行),对吗?也许 EXPLAIN ANALYZE 会很有用。
  • 是的,两个表都有几何列索引。此外,每个多边形可以包含许多点,但一个点在一个多边形内。确切的数字并不重要,我有多个数据集,这取决于机器。对于 ~5000 点和 ~1m 点,在我的数据库服务器上大约需要 15 秒。
  • 您在这两列上究竟创建了什么样的索引?请edit您的问题并为两个表添加create table 语句,包括所有create index 语句。根据 to the manual ST_Contains() 应该能够在这些列上使用 GIST 索引。正如 404 已经说过的:使用 explain (analyze, buffers) 生成的执行计划也会有所帮助

标签: postgresql postgis


【解决方案1】:

提高速度的一种方法是将subdivide 多边形变成更小的多边形。

您将创建一个新表(如果多边形经常更改,则为物化视图),对其进行索引,然后运行查询。如果细分有 128 个或更少的顶点,则默认情况下,数据将未压缩存储在磁盘上,从而使查询速度更快。

CREATE TABLE poly_subdivided AS 
   SELECT ST_SUBDIVIDE(a.geom, 128) AS geom , a.polygon_id 
   FROM poly;

CREATE INDEX poly_subdivided_geom_idx ON poly_subdivided  USING gist(geom);

ANALYZE poly_subdivided;

SELECT a.polygon_id, p.point_id
FROM poly_subdivided a
JOIN my_points p ON ST_Contains(a.geom, p.geom)

这是一个很棒的article 主题。

【讨论】:

  • 很好的提示,谢谢!这将时间减少了 50-70%,具体取决于数据集。
猜你喜欢
  • 2021-07-14
  • 1970-01-01
  • 2017-10-16
  • 2017-04-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-08-28
  • 2013-02-04
相关资源
最近更新 更多