查找超过 100K 个位置之间的距离

Posted

技术标签:

【中文标题】查找超过 100K 个位置之间的距离【英文标题】:Find the distance between greater than 100K locations 【发布时间】:2016-06-22 21:02:56 【问题描述】:

我有两个带有位置的 mysql 表,table1table2(见下文)。每个表中有 > 100K 行。我想使用它们的地理位置找到这两个表中每个位置之间的距离。

这是一个 MySQL 查询,用于查找单个地理位置之间的距离,例如 (-37.22, 88.88) 和 table1 中的所有位置之间的距离。

$lat = -37.22;
$long = 88.88;

SELECT id, latitude, longitude, name
        ((2 * 3960 *
          ATAN2(
            SQRT(
              POWER(SIN((RADIANS($lat - latitude))/2), 2) +
              COS(RADIANS(latitude)) *
              COS(RADIANS($long)) *
              POWER(SIN((RADIANS($long - longitude))/2), 2)
            ),
            SQRT(1-(
              POWER(SIN((RADIANS($lat - latitude))/2), 2) +
              COS(RADIANS(latitude)) *
              COS(RADIANS($long)) *
              POWER(SIN((RADIANS($long - longitude))/2), 2)
            ))
          )
        )) AS distance FROM table1 ORDER BY distance;

Table1
id name latitude longitude
1   foo1    -37.12   62.34
2   foo2    -47.12   72.34
3   foo3    -57.12   82.34

Table2
id name latitude longitude
1   bar1    -38.22   66.11
2   bar2    -48.22   76.11
3   bar3    -58.22   86.11

鉴于这也是一个大数据,我不知道从哪里开始。想法?

【问题讨论】:

一个重要的问题是:你想用这些距离做什么? 不确定这是否可行,但您可能会研究像 Pentaho Data Integration 这样的 ETL 解决方案? @mistermartin 看起来是后者,所以 100kx100k = 100 亿次计算。 考虑定义“发现”,这样您就可以简化问题。有时令人惊讶的是,以这种方式可以实现什么。如果您不在乎,只需计算所有 10B 距离。 我在这些新评论出现之前写下了我的答案。您要创建的是距离矩阵,用于最短路径算法或 TRSP。如果您想找到附近的位置,这是一个不同的问题,您可以使用空间索引来实现这一目标,而无需距离矩阵。 【参考方案1】:

如果您想优化旅行或靠近位置,您应该使用空间功能http://dev.mysql.com/doc/refman/5.7/en/spatial-extensions.html

但看起来您需要每次计算,所以是的,您需要进行 100 亿次操作。

我想时间在这里真的不是问题。因为一旦你拥有它,你就可以使用它。如果新位置到达,只需计算与该位置的距离。 但是你必须优化。查询中成本最高的部分是计算SIN()COS(),因此为具有这些值的每一行创建附加字段。因此,您只需执行一次,而不是每行执行 100k 次 最后运行一个循环,以便以块的形式创建数据。

编辑:

阅读您的最后一条评论后。你需要一个空间索引。与您在数据库中搜索一个 ID 的方式相同,空间索引将优化您的附近搜索。

您还可以进行框搜索。您无需搜索整个宇宙,而是围绕您的点创建一个框并在该框内进行搜索。使用普通的浮点索引你可以做这样的事情

  SELECT t1.name, t2.name,  mysql.Distancefunction(t1,t2) as distance
  from t1
  cross join t2
  WHERE t2.x between (t1.x - 0.001) and (t1.x + 0.001)   -- use x float index
    and t2.y between (t1.y - 0.001) and (t1.y + 0.001)   -- use y float index
    and mysql.Distancefunction(t1,t2) < 100 km           -- use spatial index

您可以使用 delta 0.001。如果得到太多结果,则使用 0.0001。如果你得到的结果很少,你只对那些没有 100 个邻居的位置使用 0.01 进行第二步。

【讨论】:

是的,时间不是问题。我希望能够查询生成的数据。感谢您建议只做一次sin()cos()。您能否详细介绍“在块中创建数据”的“循环”。它只是简单的for 循环在任何编程语言中与 MySQL 中的limit offset 混合吗?我从来没有做过大数据,所以我认为有更好的解决方案(不是我想花哨的)。 取决于您的需求和处理能力。如果你可以在一小时内完成select distance(*) from table1, table 2 where table1 between 1 and 10.000,那么只需复制/粘贴 10 次。只是不要一起运行,否则将作为事务处理,并将为整个过程保留临时表。 如果事情比较慢并且需要做 100 个查询,每个查询 1000 个,那么您可以创建一个脚本来发送查询

以上是关于查找超过 100K 个位置之间的距离的主要内容,如果未能解决你的问题,请参考以下文章

2 个位置之间未显示多段线,但显示了时间和距离

使用距位置的距离有效地计算最近的 5 个位置

Android - 沿街 2 个位置之间的距离和时间

如何在谷歌地图 api 中计算从 1 个位置到许多其他位置的距离? [复制]

2个位置之间的iOS GPS距离计算

万能的二分