lat / lon两个表之间的距离计算

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了lat / lon两个表之间的距离计算相关的知识,希望对你有一定的参考价值。

我有以下两个表

城市

ID年,LON

ID,纬度,经度

SELECT cities.id, 
    (SELECT id FROM mountains 
    WHERE SQRT(POW(69.1 * ( latitude -  cities.lat ) , 2 ) + 
    POW( 69.1 * (cities.lon - longitude ) * 
    COS( latitude / 57.3 ) , 2 ) )<20 LIMIT 1) as mountain_id 
FROM cities

(查询耗时0.5060秒。)

为了复杂性,我删除了查询的某些部分(例如,按顺序排列,在哪里)。但是它确实不会影响执行时间。

下面的EXPLAIN。

id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY cities ALL NULL NULL NULL NULL 478379
2 DEPENDENT SUBQUERY mountains ALL NULL NULL NULL NULL 15645 Using where

使用SELECT本身不是我的问题,但是当我尝试使用给定的结果时......例如

id mountain_id 

588437 NULL
588993 4269
589014 4201
589021 4213
589036 4952
589052 7625
589113 9235
589125 NULL
589176 1184
589210 4317

...更新表格一切都变得非常缓慢。我几乎尝试了所有我所知道的事情。我知道依赖子查询不是最佳的,但我不知道如何摆脱它。

有没有办法改善我的查询。也许把它变成一个JOIN?

除了纬度和经度之外,这两个表本身并没有什么共同点,它们是不同的,只是在使用计算时才会产生关系。

MariaDB中的空间距离搜索(km,miles)似乎尚不可用。

答案

快速进行这种操作的技巧是避免在每对可能的lat / lon点上进行所有计算。为此,您应该合并一个边界框操作。

让我们从使用JOIN开始。在伪代码中,你想要这样的东西,但是如果你抓住一些额外的对子并不重要,只要它们比其他对更远。

    SELECT c.city_id, m.mountain_id
      FROM cities c
      JOIN mountains m ON distance_in_miles(c, m) < 20

因此,我们需要弄清楚如何快速制作ON子句 - 让它使用索引而不是在所有城市和山区漫步(向Woody Guthrie道歉)。

让我们试试这个ON子句。它在+/- 20英里的方形边界框内搜索附近的对。

    SELECT c.city_id, m.mountain_id
      FROM cities c
      JOIN mountains m
                  ON m.lat BETWEEN c.lat - (20.0 / 69.0)
                               AND c.lat + (20.0 / 69.0)
                 AND  m.lon BETWEEN c.lon - (20.0 / (69.0 * COS(RADIANS(c.lat))))
                                AND c.lon + (20.0 / (69.0 * COS(RADIANS(c.lat))))

在此查询中,20.0是比较极限半径,69.0是每纬度纬度定义法定英里的常量。

然后,在两个表上的(lat, lon, id)上放置复合索引,并且您的JOIN操作将能够使用索引范围扫描来提高查询效率。

最后,您可以使用伪代码以这些类型的子句扩充该查询

       ORDER BY  dist_in_miles (c,m) ASC
          LIMIT  1

在这里,您实际上需要使用距离公式。你问题中的笛卡尔距离公式是一个近似值,除非你靠近极点,否则它可以很好地运行。您可能希望使用大圆公式。这些被称为球形余弦定律,半正弦或Vincenty公式。

以上是关于lat / lon两个表之间的距离计算的主要内容,如果未能解决你的问题,请参考以下文章

计算两个经纬地之间的距离

javascript 两个位置之间的距离(lon / lat)

在PHP中测量两个坐标之间的距离

计算几个位置之间的全局距离

计算数据框中两个长纬度坐标之间的距离

mysql实现经纬度计算两个坐标之间的距离