我正在尝试使用Postgis 2.0新功能<->(几何距离质心),以便为我的表格(cosn1)的每一行计算到同一类最近的多边形的距离。

我尝试使用以下代码:



 WITH index_query AS (
  SELECT g1.gid As ref_gid, ST_Distance(g1.the_geom,g2.the_geom) As ENN    
    FROM "cosn1" As g1, "cosn1" As g2   
    WHERE g1.gid <> g2.gid AND g1.class = g2.class
    ORDER BY g1.gid, g1.the_geom <-> g2.the_geom) 
SELECT DISTINCT ON (ref_gid) ref_gid, ENN 
    FROM index_query
ORDER BY ref_gid, ENN;
 


但后来我意识到了警告:


注意:仅当其中一个几何是常数时才启动索引(不是在子查询/ cte中)。例如'SRID = 3005; POINT(1011102 450541)':: geometry而不是a.geom


意味着完全不会使用索引,并且查询将花费几乎相同的时间像以前一样使用:

 SELECT DISTINCT ON(g1.gid)  g1.gid As ref_gid, ST_Distance(g1.the_geom,g2.the_geom) As ENN    
    FROM "cosn1" As g1, "cosn1" As g2   
    WHERE g1.gid <> g2.gid AND g1.class = g2.class
    ORDER BY g1.gid, ST_Distance(g1.the_geom,g2.the_geom)
 


谁能给我一个解决方法,让我提高性能我的查询吗?

非常感谢。

评论

您可以在where子句中使用g1.gid> g2.gid,这将减少您必须执行的距离计算的次数。不幸的是,直到<->运算符在不使用常量的情况下工作,在这种查询中我们看不到速度的提高。

约翰,我需要保留所有gid,即使是重复的gid,因为我需要为“ cosn1”表中的每个多边形更新EEN。但是你说的给了我一个主意。我可以按照您所说的使用g1.gid> g2.gis来减少距离计算,但是将g1.gid和g2.gid保留在结果中。之后,我可以合并它的两个子查询(一个以g1.gis作为gid,另一个与g2.gid)。谢谢

我发现解决该常数问题的一种可能解决方案是在SQL函数中使用the-geom作为参数使用<->。我进行了一些测试,在某些情况下,它的速度要快得多()。但就我而言,由于距离位于同一张表中,因此在此过程中会重复进行许多距离计算,这比使用直接查询要慢。
我假设在这种情况下使用ST_DWithin()不相关?另外,我也不知道它是否会有所作为,但也许您可以在第二个查询中使用SELECT .... LIMIT 1而不是SELECT DISTINCT ON

#1 楼

在我的机器上进行一些测试表明此操作符<->无法正常工作。我不确定这是一个错误,但是在不重叠的几何上它报告了零距离。
我尝试了传统的SQL查询优化。
速度上有更好的结果。
带有st_overlaps的希望语义保持不变。至少我从有关<->
的文档中了解了这一点,从Postigs上的文档<->

对于其他几何类型,返回了浮点之间的距离
边界框形心。

在我的具有约5.5k多边形的测试数据上,没有空间索引的速度从〜1000秒提高到了〜5秒。
我看到有些人使用DISTINCT ON进行分组,但没有按存在进行分组以消除重复。
使用标准SQL优化进行查询,而不会引入st_centroid错误。
select g1.gid, min( st_distance( g1.the_geom, g2.the_geom ) ) AS enn
FROM 
  "cosn1" AS g1, "cosn1" AS g2
WHERE
  g1.gid <> g2.gid
  AND g1.class = g2.class
  AND g1.the_geom && g2.the_geom
GROUP BY
  g1.gid


评论


抱歉,您的回答不能解决问题。实际上,它要快得多,但结果并不准确,因为最终结果是使用多边形的质心而不是其实际几何形状计算的。 <->的目的是优化对最接近候选对象的搜索,但最后应使用实际几何形状来计算与最佳候选对象的距离。我还尝试使用MIN \ GROUP BY代替DISTINCT ON \ ORDER BY,它似乎速度较慢。

–亚历山大·内托(Alexandre Neto)
2012年12月27日下午14:55

但是操作员<->的postgis手册指出,它对非点几何使用质心。因此,我的解决方案将为您提供类似的结果。它应该给您与您的顶部查询相同的结果。请使用运算符<->检查结果是否正确。它在我的测试数据上报告了零长度的几何图形,因此它的结果可能被破坏,并且此解决方案可以提供更准确的数据。如果您能够在一些粘贴站点上发布一些显示错误的示例记录,我们可能会发现解决方案上的缺陷。

–cavila
2012年12月27日15:11

如果您检查我的查询,则<->运算符将仅用于订购候选项,最终结果将使用实际的几何形状进行计算。无论如何,就像我之前说的,<->性能提升仅适用于定点。那是我最初的问题。

–亚历山大·内托(Alexandre Neto)
2012年12月27日在15:38

因此,您是否同意最高查询不等于最低查询?由于顺序会发生变化,因为运算符<->会ORDER BY st_centroid和st_distance给您一个不同的值?作为第一行传递DISTINCT ON子句,不同的顺序会带来不同的查询吗?有效查询将是需要提高速度的最底层查询吗?

–cavila
2012年12月27日在17:51

是的,第一个查询是为了提高最底层的查询速度。是的,它可能会给出不同的结果,因为g1.geom <-> g2.geom使用质心,这意味着第一行可能不会更近。为了使它起作用,我相信我必须对order by子句设置一个限制,例如限制10,然后提取距离的实际值。甚至可以使用<#>代替,它使用边界框而不是质心。

–亚历山大·内托(Alexandre Neto)
2012年12月27日20:33