如何通过经纬度计算距离来优化 SQL 查询?

Posted

技术标签:

【中文标题】如何通过经纬度计算距离来优化 SQL 查询?【英文标题】:How to optimize SQL query with calculating distance by longitude and latitude? 【发布时间】:2010-06-22 14:14:09 【问题描述】:

我有一张这样结构的表格:

table name: shop

id_shop      int(10)
name         varchar(200)
latitude     double
longitude    double

我想计算给定坐标和保存在数据库中的坐标之间的距离。

我当前的查询:

SELECT *
  FROM `shop` AS `s`
 WHERE
      (
        ( 6371
        * ACOS(
            SIN( RADIANS( latitude ) )
          * SIN( RADIANS( 53.5353010379 ) )
          + COS( RADIANS( latitude ) )
          * COS( RADIANS( 53.5353010379 ) )
          * COS( RADIANS( 14.7984442616 ) - RADIANS( longitude ) )
          )
        )
        <= 25
      )

加上一些JOIN LEFT 的一些数据。

有没有办法优化那个查询? 加入连接大约需要 13 毫秒。

我还需要在此处添加一些 LIMITCOUNT(*) 以获取用于分页的商店总数。

【问题讨论】:

您希望比 13 毫秒快多少? 实际上可能不快于 13 毫秒,但在我的系统中,对于不同的给定坐标 + 分页,会有许多类似的查询。我正在寻找一些最好的方法来处理这个问题。 给定的坐标来自另一个表格,还是来自谷歌地图的点击或移动设备坐标? 我用谷歌地图的地理定位脚本得到它们。 【参考方案1】:

这里有一些想法,根据您的具体情况,其中一些可能不适用。

    您可以将纬度和经度转换为弧度并将其存储在行中。这样可以节省这些计算的成本(实际上是在存储数据时计算一次成本)。 如果您的表非常大,您可以使用简单的线性距离计算而不是 Haversince 公式来限制应用 Haversince 公式的结果。 如果表中还有其他数据可用作良好的第一个过滤器(国家/地区/等),您可以先应用它。 您可以对联接重新排序,以便在距离过滤器之后应用它们,这样您就不会因不符合条件的数据而产生联接成本。

【讨论】:

1.好主意——我应该考虑一下; 2. 是的,桌子很大。线性计算应该如何? 3. 我没有那个数据; 4. 它没有改变任何东西。 2.基本上,你可以只使用毕达哥拉斯定理来计算距离——这可以“足够好”,这取决于你的数据和你在做什么,当你只是在寻找地球上相当有限的区域时,这很好“最近的东西”而不是实际需要准确的距离。您还可以使用 Pythagoras 进行粗略计算以缩小数据集范围,然后对缩小的较小数据集进行更准确、成本更高的 Haversine 计算。【参考方案2】:

嗯,首先,您可以在存储纬度和经度时将预先计算的内容存储在数据库中。例如,如果您将纬度和经度预先存储为弧度,则只需在存储每个位置时计算一次 RADIANS(latitude) 和 RADIANS(longitude),而不是每次需要计算距离时(大概不止一次。)

当您第一次填充行时,也可以通过存储 SIN(RADIANS(latitude)) 和 COS(RADIANS(latitude)) 来减少更多...

我猜你随着时间的推移做了很多很多“最接近 X”的计算——这就是人们在面对这种计算时通常会做的事情——而预先计算你能做的通常是第一件事试试看。

【讨论】:

以上是关于如何通过经纬度计算距离来优化 SQL 查询?的主要内容,如果未能解决你的问题,请参考以下文章

mysql中如何根据经纬度优化这个距离查询

翻译SQL最近位置查询语句(MySQLPostgreSQLSQL Server)

MySQL:使用自定义函数计算经纬度之间的最短距离

mysql使用sql语句根据经纬度计算距离排序

sql server2008根据经纬度计算两点之间的距离

sql (mysql)怎么实现查询某一个经纬度周围500米距离的餐馆,数据库存放所有餐馆的经纬度?