在PostGIS的K近邻查询(K-Nearest Neighbor Query in PostGIS

2019-06-24 04:36发布

我使用了PostGIS以下最近邻查询:

SELECT g1.gid g2.gid FROM points as g1, polygons g2   
WHERE g1.gid <> g2.gid
ORDER BY g1.gid, ST_Distance(g1.the_geom,g2.the_geom)
LIMIT k;

现在,我已经创建了the_geom指标以及GID列上两个表,这种查询花费更多的时间比其他空间查询涉及空间连接的B / W两个表。

有没有更好的方式来寻找K最近邻居? 我使用的PostGIS。

而且,它走的是一条不寻常的很长一段时间,尽管创建索引的几何列另一个查询是:

select g1.gid , g2.gid from polygons as g1 , polygons as g2
where st_area(g1.the_geom) > st_area(g2.the_geom) ;

我相信,这些查询的arent要点索引中受益,但是为什么呢?

鉴于此查询:

select a.polyid , sum(length(b.the_geom)) from polygon as a , roads as b  
where st_intersects(a.the_geom , b.the_geom);

一段时间后,返回结果,尽管涉及“道路”表比多边形或分表大得多,并且还涉及更复杂的空间操作。

Answer 1:

只是你的问题的一些想法:

st_distance以及st_area无法使用索引。 这是因为这两种功能不能被减少到这样的问题“是B内?” 或“做A和B的重叠?”。 更具体:GIST-指数只能在两个物体的边界框进行操作。

有关它的更多信息,你简直看在PostGIS的手册 ,其中规定与st_distance以及如何查询可以改善有更好的表现的例子。

然而,这并不能解决您的k最近邻问题。 对于这一点,现在我没有一个好主意,如何提高查询性能。 我看到的唯一的机会将被假设k个最近的邻居总是低于X米的距离。 然后,作为PostGIS的手动完成的,你可以使用类似的方法。

你的第二个查询可以加快一点。 目前,您计算在表1中经常每个对象的面积表有行 - 策略是第一个加入的数据,然后选择基于该功能。 你可以减少面积计算显著可以预先计算领域的计数:

WITH polygonareas AS (
    SELECT gid, the_geom, st_area(the_geom) AS area
    FROM polygons
)
SELECT g1.gid, g2.gid
FROM polygonareas as g1 , polygonareas as g2 
WHERE g1.area > g2.area;

你的第三个查询可以用包围盒来显著优化:当两个物体的边界框不重叠,没有办法中的物件。 这使得一个给定的指标,因此巨大的性能增益的使用。



Answer 2:

自2011年9月下旬 ,PostGIS中已经支持通过一个特殊的运算符(S)在ORDER BY子句中使用索引的近邻查询:

SELECT name, gid
FROM geonames
ORDER BY geom <-> st_setsrid(st_makepoint(-90,40),4326)
LIMIT 10;

...将返回10个对象,其geom最接近-90,40可伸缩的方式。 一些更多的细节(选项和注意事项),是在公告后和使用的< - >和的<#>运营商现在也官方PostGIS的2.0参考文件。 (两者之间的主要区别是, <->比较形状重心和<#>比较它们的边界-对分没有区别,其他形状选择什么是适合你的查询。)



Answer 3:

你可能需要的是KNN指数而即将在PostGIS的2.x和9.1 PostgreSQL的希望:请参见http://blog.opengeo.org/tag/knn/



Answer 4:

你可以用KNN指数做到这一点,横向连接。

SELECT v.gid, v2.gid,st_distance(v.the_geom, v2.the_geom)
  FROM geonames v, 
       lateral(select * 
                 from geonames v2
                where v2.id<>v.id
                ORDER BY v.the_geom <-> v2.the_geom LIMIT 10) v2
where v.gid in (...) - or other filtering condition


Answer 5:

假设你有p指向和g的多边形,原始查询:

SELECT g1.gid, g2.gid FROM points as g1, polygons g2   
WHERE g1.gid <> g2.gid
ORDER BY g1.gid, ST_Distance(g1.the_geom,g2.the_geom)
LIMIT k;

在返回k个最近的邻居在PXG集。 该查询可能会使用索引,但它仍然有权责令其整个PXG设置为找到的最小距离的k行。 你不是想要的是以下几点:

SELECT g1.gid, 
      (SELECT g2.gid FROM polygons g2   
       --prevents you from finding every nearest neighbour twice
       WHERE g1.gid < g2.gid 
       --ORDER BY gid is erroneous if you want to limit by the distance
       ORDER BY ST_Distance(g1.the_geom,g2.the_geom)
       LIMIT k)
FROM points as g1;


文章来源: K-Nearest Neighbor Query in PostGIS