2

我正在编写一个应用程序,该应用程序需要允许用户选择其位置半径范围内的元素。没有办法知道最终会有多少个位置,但它可能是数万个。进行搜索的用户是位置节点之一(而不仅仅是他们的手机或其他提交的任意位置)

我看到这样的答案:mysql lat lon calculation to show locations within radius但我担心这是一项非常严肃的工作,因为需要为每个“其他”位置计算所涉及的数学。

我正在考虑的另一种方法是有一个关系表来标识每个位置之间的距离(每次添加位置时我都会填充),授予它将有大量行来定义每个可能的关系,然后选择反对 *该表将非常快,尤其是在对距离进行索引的情况下。

希望从在 mySQL 中完成此操作的人那里获得一些建议,并且可以警告/建议我支持或反对最佳方法。

4

3 回答 3

2

以下 SQL 查询使用球面余弦定律计算坐标与表中坐标之间的距离。它将结果限制为 10 并按距离排序。这用于代替过于复杂而无法使用 MySQL 执行的 Haversine 公式

球面余弦定律

其中 R = 3,959 英里或 6,371 公里

d = acos( sin(lat1).sin(lat2) + cos(lat1).cos(lat2).cos(lng2-lng1) ).R

SQL

SELECT  name, lat, lng, ( 3959 * acos( cos( radians($center_lat) ) 
                        * cos( radians( lat ) ) * cos( radians( lng )
                        - radians($center_lng) ) + sin( radians($center_lat) ) 
                        * sin( radians( lat ) ) ) ) AS distance FROM table 
                        ORDER BY distance LIMIT 0 , 10

Where $center_lat&$center_lng是位置坐标。

查询使用SQL 数学函数

在 50,068 行的数据库上查询耗时 0.2506 秒

MySQL 中可用的空间函数不适合您的 porpose 请参阅此博客

于 2014-10-24T11:22:27.510 回答
1

GIS 是开始计算半径距离的好地方,但最终(规模)您将不得不分解为纬度/经度网格。Radius 计算成本很高,因为网格在哪里存储和查找非常简单。根据我的经验,MySQL 中的 FWIW GIS 功能在 5.6 之前的许多内核(10+)上不能很好地扩展,并且可能要到 5.7 才能修复。

于 2014-10-24T04:20:46.657 回答
0

如果您预先计算了一些您实际需要的数据并将其存储在数据库中,那么根据该数据进行一些计算应该会非常快。

根据我对这个问题的回答:

在 SO 上排序邮政编码邻近问题

您可以使用类似的计算

$iRadius * 2 * ASIN(SQRT(POWER(SIN(( $fLat - abs(pos.lat)) * pi() / 180 / 2),2) +
COS( $fLat * pi()/180) * COS(abs(pos.lat) * pi() / 180) * POWER(SIN(( $fLon - pos.lon) *
pi() / 180 / 2), 2) )) AS distance

其中实际数学函数的负载可以预先计算,也可以存储在数据库中。这应该可以帮助您加快查询速度。

如果您知道您只对特定半径感兴趣,您甚至可以忽略差异较大的纬度/经度值(因为这已经暗示它们具有特定距离),因此您只需计算纬度/经度值您所在位置的特定范围。

我使用这种方法在 0.1 秒内计算到邮政编码 (>60.000) 的距离

问题始终是:您需要计算多少个值?

于 2014-10-24T06:05:12.967 回答