Эффективно присваивать точки полигонам - PullRequest
0 голосов
/ 25 марта 2019

У меня есть таблица многоугольников (тысячи) и таблица точек (миллионы).Обе таблицы имеют индексы 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.Есть идеи?

1 Ответ

2 голосов
/ 25 марта 2019

Способ увеличить скорость - это подразделить полигонов на более мелкие.

Вы должны создать новую таблицу (или материализованное представление, если многоугольник часто меняется), проиндексировать ее, а затем выполнить запрос. Если подразделения имеют 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)

Вот отличная статья по теме.

...