【问题标题】:Group polygons with Postgis (beginner)使用 Postgis 对多边形进行分组(初学者)
【发布时间】:2020-04-12 13:34:42
【问题描述】:

大家早上好,我正在尝试将相互接触的多边形组合成一个多边形。

我使用以下公式:

drop table if exists filtre4;
create table filtre4 as
(

select st_unaryunion(unnest(st_clusterintersecting(geom))) as geom
    from data
)

当我的物品少于 6,000,000 件时,它可以完美运行。 示例:我出现了这条正常消息,其中包含创建的实体数量。 https://zupimages.net/viewer.php?id=20/15/ielc.png

但如果我超过 6,000,000 个实体,则查询结束,但不会在表中创建任何元素。我有这条消息显示出来,但没有返回任何东西给我。 https://zupimages.net/viewer.php?id=20/15/o41z.png

我不明白。

谢谢。

【问题讨论】:

  • 听起来是内存问题。让我们知道 geohasholing 是否如本例中给出的那样工作:gis.stackexchange.com/questions/31880/…
  • 感谢您的回复。你认为这个内存问题可能来自 postgresql.conf 的错误配置吗?我从来没有真正优化过它,而且我有一台最近的电脑(16Gb RAM,I7 第 8 代)我不知道 st_geohash,学习新东西总是好的。不幸的是,我发现它很难适应我的问题!我应该把它放在我的公式中的什么位置?
  • 我将用一些可能的解决方法写一个答案。错误日志中是否有任何内存问题的迹象?您可以在错误日志中发布任何可能的消息吗?它确实说成功,所以可能没有。
  • 谢谢。不幸的是,没有。

标签: postgis


【解决方案1】:

所以,我认为您使用 PgAdmin 来运行查询。奇怪的是,有时即使出现内存错误或其他运行时错误,您也不会收到通知。 (我在测试时也遇到了同样的情况。)在这种情况下,我建议您将查询保存为 sql 文件并使用 psql 运行它以确保您收到错误消息:

psql -U #your_username -d #your_database -f "#your_sqlfiile.sql"

首先我要做的是在 postgresql.conf 中调整“work_mem”。默认值为 4MB,考虑到您的规格,您可能可以为每个操作处理更多内存。根据以下文章,我建议从 64MB 开始:

https://wiki.postgresql.org/wiki/Tuning_Your_PostgreSQL_Server

请确保在这样做后重新启动您的服务器。

因此,我使用了可比较的数据集并收到了内存问题。调整 work_mem 是第一部分。 Geohashing 适用于您的数据集,因为您需要较小的集群组以适应内存中的处理,并且 geohashing 允许您在空间上对几何元素进行排序,从而减少运行 ST_CLUSTERINTERSECTING 时所需的排序操作量(我不根据我的理解,认为您具有可以分组的属性)。以下是以下示例的作用:

  1. 如果存在则创建输出表或截断,如果存在则创建序列或重置它
  2. "ordered" 从输入表中拉取几何图形,并按其 geohash 排序(*几何图形必须采用度数单位,如 EPSG 4326 才能进行 geohash)
  3. "grouped" 使用序列将数据放入 x 个组中。我在这里除以 10,000,但想法是您的实体总数除以 x 将为您提供 y 个组。尝试使组足够小以适应内存,但又足够大以提高性能。然后,它获取每个组,执行 ST_CLUSTERINTERSECTING、unnest,最后是 ST_UNARYUNION。
  4. 使用 ST_COLLECT 和几何的另一个 ST_UNARYUNION 插入值。

代码如下:

DO $$
DECLARE
    input_table VARCHAR(50) := 'valid_geom';
    input_geometry VARCHAR(50) := 'geom_good';
    output_table VARCHAR(50) := 'unary_output';
    sequence_name  VARCHAR(50) := 'bseq';
BEGIN
    IF NOT EXISTS (SELECT 0 FROM pg_class where relname = format('%s', output_table)) 
    THEN
        EXECUTE '                                                        
        CREATE TABLE ' || quote_ident(output_table) || '( 
           geom geometry NOT NULL)';
    ELSE
        EXECUTE '                                                        
        TRUNCATE TABLE ' || quote_ident(output_table);                                                         
    END IF;
    IF EXISTS (SELECT 0 FROM pg_class where relname = format('%s', sequence_name)) 
    THEN
        EXECUTE '                                                    
        ALTER SEQUENCE ' || quote_ident(sequence_name) || ' RESTART';
    ELSE
        EXECUTE '                                                    
        CREATE SEQUENCE ' || quote_ident(sequence_name);
    END IF;

    EXECUTE '                                                        
    WITH ordered AS (
      SELECT ' || quote_ident(input_geometry) || ' as geom
      FROM ' || quote_ident(input_table) || '
      ORDER BY ST_GeoHash(geom_good)
    ),
    grouped AS (
      SELECT nextval(' || quote_literal(sequence_name) || ') / 10000 AS id, 
      ST_UNARYUNION(unnest(ST_CLUSTERINTERSECTING(geom))) AS geom
      FROM ordered
      GROUP BY id
    )

    INSERT INTO ' || quote_ident(output_table) || '
    SELECT ST_UNARYUNION(ST_COLLECT(geom)) as geom FROM grouped';

END;    
$$;

注意事项:

  1. 根据需要更改声明变量。

  2. 由于您的输入几何图形被命名为“geom”as geom 将失败,所以我会将 SELECT ' || quote_ident(input_geometry) || ' as geom 更改为 SELECT ' || quote_ident(input_geometry)

  3. 确保所有输入几何都有效,否则 ST_UNARYUNION 将失败。结帐 ST_ISVALID 和 ST_MAKEVALID。

  4. 如前所述,地理散列要求投影以度为单位。检查 ST_TRANSFORM,(我将几何数据转换为 4326)。

如果您还有其他问题,请告诉我。

【讨论】:

    猜你喜欢
    • 2014-05-29
    • 2020-05-19
    • 2017-02-09
    • 2016-09-27
    • 2021-11-07
    • 1970-01-01
    • 2014-07-12
    • 2021-07-02
    • 2016-09-28
    相关资源
    最近更新 更多