与经度相距x距离的最大纬度 - 与纬度相距x距离的最大经度 - SQL

时间:2016-05-04 03:52:04

标签: mysql math latitude-longitude

现在我有一个包含1亿个插页的表格:

CREATE TABLE o (
    id          int UNIQUE,
    latitude    FLOAT(10, 8),
    longitude   FLOAT(11, 8)

);

在我的后端,我收到一个用户lat / long并尝试返回x距离内的所有内容。

我没有在每一个结果上做距离公式,而是认为我可以计算X距离的最大纬度/长度。

所以我们通过找到max lat / min lat,max long / min long来创建一个正方形。

一旦我们得到这些最大值,我们就会对这个值范围进行查询,从而使我们的子集显着变小,然后在实际的距离公式上(即找到X距离内的值)。

所以我的问题是: 是什么让我跑得更快?

选项1)

  • 获得设置的1亿个条目的距离公式。

选项2)

  • 我们计算最小/最大纬度/长度,而不是在1亿个条目的集合上进行距离公式。
  • 从包含1亿条目的表中选择该范围内的值
  • 在我们新的小集上做距离公式。

选项3)

  • SQL
  • 中已存在某些内容

如果选项2更快,则下一个问题实际上是解决了数学问题。

如果你想继续阅读:

纬度/长距离公式

dlon = lon2 - lon1
dlat = lat2 - lat1
a = (sin(dlat/2))^2 + cos(lat1) * cos(lat2) * (sin(dlon/2))^2
c = 2 * atan2(sqrt(a), sqrt(1-a)) 
d = R * c

显然我们可以重新排列这个因为D(假设1英里),而R(是地球的半径)是一个设定值,所以我们得到D / R = C.

问题在于我们如何计算C / 2 = atan2(sqrt(a),sqrt(1-a))?

1 个答案:

答案 0 :(得分:0)

1 - 100M行是很多要扫描和测试的。可以偶尔做一次,但是做太多事情太慢了。

2 - 使用伪方形边框并执行

WHERE latitude  BETWEEN ...
  AND longitude BETWEEN ...

是一个很好的第一步。纬度范围是一个简单的常数X;经度范围也除以cos(latitude)

但是当你试图在广场上找到那些行时问题就出现了。 latitude和/或longitude上的索引的任意组合(单独或一起)将仅部分过滤。也就是说,它将忽略经度并为您提供纬度范围内的所有内容,反之亦然。这可能会让你下降到100,000行来检查距离。这比100,000,000好很多,但不如你希望的那么好。

3 - http://mysql.rjweb.org/doc.php/latlng下到广场,或非常接近。它旨在扩展。我只测试了3M行,而不是100M,但它应该可以正常工作。

主要技巧是在纬度上进行分区,然后将经度作为PRIMARY KEY中的第一列,以便InnoDB将分区附近的附近行聚类。如果您查找X英里(或公里)内的所有行,它可能会查看(并计算大圆距离)大约两倍的行,而不是100K。如果你想找到最近的100个项目,它可能会触及约400(4x)。

对于SPATIAL索引,您可能希望升级到5.7.6,即添加ST_Distance_Sphere()ST_MakeEnvelope()时。 (MakeEnvelope只比你自己构建一个Polygon更方便 - 它有扁平地球综合症。)