从给定点找到特定半径内的点的最有效方法

时间:2016-04-01 13:54:23

标签: postgresql postgis postgresql-9.3

关于这个主题,我在这里读了几个问题+答案,但是我无法理解哪个是常见的方式(如果有一个......)找到所有的点在一个“圆圈”中有一个某个半径,以给定点为中心。

特别是我找到了两种看起来最有说服力的方法:

select id, point 
from my_table 
where st_Distance(point, st_PointFromText('POINT(-116.768347 33.911404)', 4326)) < 10000;

select id, point 
from my_table 
where st_Within(point, st_Buffer(st_PointFromText('POINT(-116.768347 33.911404)', 4326), 10000));

哪种查询数据库最有效?还有其他选择吗?

3 个答案:

答案 0 :(得分:2)

创建缓冲区以找到点是一个明确的禁忌,因为(1)创建表示缓冲区的几何体的开销,以及(2)多边形点计算的效率远低于简单点距离计算。

您显然正在处理(经度,纬度)数据,因此您应该将其转换为适当的笛卡尔坐标系,该坐标系具有与10,000距离相同的度量单位。如果该距离以米为单位,那么您也可以将该点从表格转换为geography并直接计算(长,纬度)坐标。由于您只想识别指定距离内的点,因此您可以在球体上使用ST_DWithin() function计算增加的​​速度(在非常高的纬度或非常长的距离时不要这样做):

SELECT id, point 
FROM my_table 
WHERE ST_DWithin(point::geography,
                 ST_GeogFromText('POINT(-116.768347 33.911404)'),
                 10000, false);

答案 1 :(得分:0)

我使用了以下查询

SELECT *, ACOS(SIN(latitude) * SIN(Lat)) + COS(latitude) * COS(Lat) * COS(longitude) - (Long)) ) * 6380 AS distance FROM Table_tab WHERE ACOS( SIN(latitude) * SIN(Lat) + COS(latitude) * COS(Lat) * COS(longitude) - Long )) * 6380 < 10

在上面的查询中,纬度和经度来自数据库和纬度,long是我们要搜索的点。

工作:它将计算数据库中所有点与搜索点之间的距离(以KM为单位),并检查距离是否小于10公里。它将返回10公里内的所有坐标。

答案 2 :(得分:0)

我不知道postgis如何做到最好,但总的来说:

根据您的数据,最好先在方形的边界框(其中包含搜索区域的圆圈)中进行搜索,以消除大量候选对象,这应该非常快可以在lon / lat上使用简单的范围运算符,为此,它们应该正确地索引。 在第二步中,使用半径进行搜索。

此外,如果您的极限最大点数相对较低,并且您知道有很多候选人,那么您可以对圈子内的方框进行第一次“乐观”尝试,如果发现足够的点数就可以完成!