我想创建一个大型GPS坐标数据库,可以通过说“返回[此坐标]'n'米范围内的所有坐标来查询。
我需要它尽可能高效,因此循环遍历数据库中的所有坐标并计算坐标是否在'n'米范围内不是理想的解决方案。
有更简单的解决方案吗?
由于
答案 0 :(得分:6)
我通常使用lat / lon进行此类查询。使用球面几何体,您可以在特定点周围放置边界框。例如,假设您有一个点(X,Y),您希望所有坐标都在1英里范围内(转换为米,我将作为练习留给读者)。您可以确定(X-1,Y-1),(X + 1,Y + 1)的边界框。然后使用BETWEEN运算符查询点数据库(SELECT foo FROM bar在X-1和X + 1之间的距离和在Y-1和Y + 1之间的距离)。然后,将细节距离计算为“围绕边界框的角”。
需要注意的是,经度线在球体的顶部更靠近在一起,所以你会得到偏离的结果,你离赤道越远。但它仍然可以快速过滤掉您的结果集。
Google“Great Circle Distance”用于计算。
编辑:每英里有0.167469度经度(实际范围从0.167469到0.014564),每英里有0.014483度纬度。所以你的边界框是(lat - (miles * 0.014483), lon - (miles * 0.167469)), (lat + (miles * 0.014483), lon + (miles * 0.167469))
答案 1 :(得分:2)
SQL Server 2008中支持存储spatial data。我自己从未使用它,但我知道你可以创建你想要的类型的查询。
答案 2 :(得分:0)
许多数据库系统都具有处理地理空间数据的功能。
这是SQL Server 2008,PosGIS和MySQL之间的比较地理空间功能 http://www.bostongis.com/PrinterFriendly.aspx?content_name=sqlserver2008_postgis_mysql_compare
答案 3 :(得分:0)
如果您可以选择DB,我建议使用与rwwilden相同的内容,并使用SQL 2008及其空间数据功能。如果您无法使用该解决方案或包含空间查询的解决方案,您可以查看Microsoft在Hierarchical Triangular Mesh上自己的论文并实现这些内容。用于MSSQL '05的SDK也提供了一个完整的HTM开箱即用解决方案,因此您可以将其转换为您正在使用的任何平台。
编辑:
以下是解释HTM和实现的更多细节document。您当然可以转换为您选择的数据库。您可以在SDK for 2005中找到完整HTM实现的源代码。
答案 4 :(得分:0)
GIS数据库(MS PostgreSQL等)实际上为二维或三维区域搜索(spatial indices)实现了一些数据结构。最简单的结构是网格索引,然后是不同的搜索树(kd-tree,quad-tree),其中R-tree是最常用的(更多维度的广义B树)。这些方法似乎足够了。
基本的网格索引(将空间划分为网格单元,仅在附近的单元格中搜索)可以轻松实现,并且可以将搜索时间缩短为对数。搜索树有点难以实现,但是有许多编程语言的开源实现。但是,在大多数情况下,网格索引足够有效。
答案 5 :(得分:0)
跟进Erich - 如果你有你的选择使用PostGIS(postgresql)它是免费和开源的,你所描述的查询非常快,几乎在所有平台上运行,我提到它是免费的吗?
答案 6 :(得分:0)
如果你想避免GIS扩展,我改编了从this post到postgres sql的函数:
create or replace function change_in_lat(miles numeric)
returns double precision as $$
with v as (select
3960.0 as earth_radius,
180 / pi() as radians_to_degrees
) select ( miles / earth_radius ) * radians_to_degrees from v;
$$ language sql
returns null on null input;
create or replace function change_in_long(lat numeric, miles numeric)
returns double precision as $$
with v as (select
3960.0 as earth_radius,
pi() / 180 as degrees_to_radians,
180 / pi() as radians_to_degrees
) select (
miles / (earth_radius * cos(lat * degrees_to_radians))
) * radians_to_degrees from v;
$$ language sql
returns null on null input;
使用那些你可以做一些围绕方形查询:
--find all "a"s within 25 miles of any "b"
select * from a join b on (
a.gpslat between
b.gpslat - change_in_lat(25) and b.gpslat + change_in_lat(25)
and a.gpslong between
b.gpslong - change_in_long(b.gpslat::numeric, 25)
and b.gpslong + change_in_long(b.gpslat::numeric, 25)
);
如果你经常使用它我肯定将两个语句转换成单个函数会很容易。我从来没有做过任何实际的“半径内”查询。
对于任何更复杂的事情,你可能想要像其他答案所说的GIS扩展。 PostGIS很好,但我发现很多gis特定的功能很难正确,除非你使用边界框索引,否则如果你的数据集足够大,你的空间查询可能需要一天。但复杂性的权衡对于所有奇特的东西来说都是值得的,例如以geojson格式输出数据等。
答案 7 :(得分:0)
我们可以使用Geohash算法。
土拨鼠的美丽在于其构造方式。简而言之,地理哈希是一种网格空间索引,其中,将世界递归地划分为越来越小的网格,每增加一个位。 (https://www.mapzen.com/blog/geohashes-and-you/)
您可以在Wikipedia(https://en.wikipedia.org/wiki/Geohash)上找到其说明。
为了快速直观地介绍了下一个视频。
https://www.youtube.com/watch?v=UaMzra18TD8
https://youtu.be/mx1mMdHBi5Q?t=1955
在下一篇文章中,您可以找到针对AWS数据库DynamoDB的这种算法的实现。 https://read.acloud.guru/location-based-search-results-with-dynamodb-and-geohash-267727e5d54f
请为James Beswick的文章鼓掌。