查找超过 100K 个位置之间的距离
Posted
技术标签:
【中文标题】查找超过 100K 个位置之间的距离【英文标题】:Find the distance between greater than 100K locations 【发布时间】:2016-06-22 21:02:56 【问题描述】:我有两个带有位置的 mysql 表,table1
和 table2
(见下文)。每个表中有 > 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 个位置之间的距离的主要内容,如果未能解决你的问题,请参考以下文章