使用GIST索引(<->函数)的Postgis 2.0中的最近邻居问题


25

我正在尝试使用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)

谁能为我指出一种解决方法,使我能够提高查询性能?

非常感谢你。


尚无答复,您可能想在PostGIS邮件列表中询问。
GIS乔纳森(Jonathan)

我已经做了,但是也没有任何回应。
亚历山大·内托

3
您可以在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作为参数。我进行了一些测试,在某些情况下,它的速度要快得多()。但就我而言,由于距离位于同一张表中,因此在此过程中会重复进行许多距离计算,这使其比使用直接查询要慢。
亚历山大·内托

Answers:


2

嗡嗡声在我的机器上做一些测试,听起来像此操作符<->无法正常工作。我不确定这是一个错误,但是在不重叠的几何图形上它报告了零距离。有意思吗?

那么公平的传统SQL查询优化又如何呢?由于使用<->运算符的那些意外结果,我将其替换为st_centroid。在速度上有更好的结果。

希望st_overlaps的语义保持不变。至少我从有关<->的文档中了解到

来自Postigs上的文档<->

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

在我的具有约5.5k多边形的测试数据上,没有空间索引的速度从约1000秒增加到了约5秒。

无论如何,为什么要使用DISTINCT ON进行分组?我看到有人在使用它,但是group by不是为了消除重复项而存在吗?

使用标准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,它似乎速度较慢。
亚历山大·内托

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

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

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

是的,第一个查询旨在提高最底层的查询速度。是的,它可能会给出不同的结果,因为g1.geom <-> g2.geom使用质心,这意味着第一行可能不会更近。为了使它起作用,我相信我必须对order by子句设置一个限制,例如限制10,然后提取距离的真实值。甚至可以使用<#>代替,它使用边界框而不是质心。
亚历山大·内托
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.