【问题标题】:Very large number of SQL UNION SELECT statements exceeds max_stack_depth非常多的 SQL UNION SELECT 语句超过了 max_stack_depth
【发布时间】:2019-01-05 11:22:02
【问题描述】:

我正在尝试为一组给定多边形中的一个或多个内的所有唯一点开发基于空间的 SQL 查询。我在具有 6 个 vCPU 和 16 GB RAM 的云 VPS 上使用 PostGIS。有问题的空间测试是 WHERE 子句上的 ST_Contains。多边形集包含大约 40,000 个独特的几何图形,它们约束着 370 万个特征点数据集。

我的问题是,当我创建一个包含超过 13,000 个多边形的查询(因此有 13,000 个 SELECT 语句)时,PostGIS 服务器会以ERROR: stack depth limit exceeded" 进行响应 HINT: Increase the configuration parameter "max_stack_depth"

我想知道为什么以及是否可以解决它。

这是优化练习的一部分。我已经将多边形几何作为单独的 SELECT 检索以形成所需的 SQL 查询。我想执行将多边形集测试为单个 SQL 语句的查询。到目前为止,我一直在为每个多边形构建一个 SELECT 子查询,然后将每个 UNION 一起作为起点。编译后,仅使用 13,000 个多边形的查询约为 28,000,000 个字符,我认为这远低于 PostGIS SQL 语句的限制。

我尝试了较小的尺寸,发现正常性能达到了近似极限。我之前已经达到了这个限制,但是在听取了错误消息的建议后,我将“max_stack_depth”增加到了大约“ulimit -s”返回的大小。以我目前的理解,此 SQL 语句不是任何类型的递归函数,我认为这会导致超出堆栈深度。

此外,从我对堆栈与堆内存的阅读中,我无法理解为什么此查询会使堆栈过载,因为大多数所需的存储数据最终都应该在堆中。我还希望查询在收集结果时按顺序执行,但似乎 PostGIS 可能首先运行所有 SELECT 子语句,然后计算结果。

我选择不尝试将单个多边形几何图形合并为一个多边形,因为它们覆盖了地理上非常多样化的区域(即不聚集成一个简单的块),我认为这会大大降低空间索引的好处。

我当前的工作 SQL 脚本遵循模式(修剪以适应这篇文章):

SELECT * FROM point_table WHERE ST_Contains("poly1_geom_str", pt_geom_col)
UNION
SELECT * FROM point_table WHERE ST_Contains("poly2_geom_str", pt_geom_col)
UNION
....
SELECT * FROM point_table WHERE ST_Contains("polyN_geom_str", pt_geom_col);

我构造这条 SQL 语句的策略是不是不太可能解决?有没有我可以尝试的替代策略来避免递归问题?

【问题讨论】:

    标签: sql postgresql postgis


    【解决方案1】:

    您可以尝试查询的这种变体。它从不同的多边形字符串创建一个临时表,然后基于ST_Contains 执行连接:

    SELECT  DISTINCT point_table.* 
    FROM    point_table 
    JOIN    (values ("poly1_geom_str"), 
                    ("poly2_geom_str")
            ) as polys(poly_str)
         ON ST_Contains(poly_str, pt_geom_col)
    

    当然,如果这些几何图形实际上来自现有表,那么只需加入该表即可:

    SELECT  DISTINCT point_table.* 
    FROM    point_table 
    JOIN    polys
         ON ST_Contains(poly_str, pt_geom_col)
    

    【讨论】:

    • 你能解释一下为什么不同吗?
    • 一个点可能位于多个多边形中,然后此查询将多次列出该点。 distinct 防止这种情况发生。
    • @RémiDesgrange:原始查询中的 UNION 也意味着 DISTINCT
    • @trincot 这让我超越了之前的限制,成功完成了40,000的完整查询。但是,我仍然想了解导致我的原始查询以确切方式失败的后台发生的事情。
    • 我不知道 PostgreSQL/PostGIS 的内部原理来回答这个问题,但是可以理解的是,具有 13,000 个union 操作的大型 SQL 语句将在编译和优化中产生巨大的影响引擎的阶段(甚至在执行之前)。其他人对如此大的查询也有类似的经历。例如,请参阅this thread,其中使用与 GIS 无关的 8000xunion all 查询报告错误。
    【解决方案2】:

    你考虑过or吗?

    SELECT *
    FROM point_table
    WHERE ST_Contains("poly1_geom_str", pt_geom_col) OR
          ST_Contains("poly2_geom_str", pt_geom_col) OR
          ....
          ST_Contains("polyN_geom_str", pt_geom_col);
    

    【讨论】:

    • 我已经尝试过了,抱歉我没有将它添加到 OP 中。此策略适用于少量多边形,但随着多边形数量的增加,计算资源将迅速受到限制。我相信这是因为,对于每个额外的多边形,额外的 ST_Contains() 函数将再次扫描整个点表。这种策略只能完成大约 1000 个多边形。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-04-21
    • 2019-01-08
    • 2013-09-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多