【问题标题】:Tracking GPS points and finding their nearest neighbours?跟踪 GPS 点并找到最近的邻居?
【发布时间】:2013-06-08 20:17:07
【问题描述】:

我有一个全球 100 万个(缓慢)移动点的列表(存储为纬度和经度)。时不时地,每个点都会请求 100 个最近的其他点的列表(如果有帮助,可以使用可配置的最大范围)。

不幸的是,SELECT * SORT BY compute_geodetic_distance() LIMIT 100 太慢了,每个点都一遍又一遍地完成。所以我的问题是:我应该如何有效地处理这个问题?有没有更好的算法/数据结构/......为此而闻名?或者这是唯一的方法,我应该考虑分配服务器负载吗?

(注意:这是针对 Android 应用程序,重点是用户,所以如果我缺少特定于 android 的解决方案,请随时说出来!)

【问题讨论】:

  • @eggyal,不是二维索引问题,将一百万次操作减少到数百次。

标签: android mysql algorithm gps nearest-neighbor


【解决方案1】:

除了 r-tree 或四叉树,即空间索引,您还可以使用四键和怪物曲线。这条曲线减小了尺寸并完全填满了空间。你可以从 phpclasses.org 下载我的 php 类希尔伯特曲线。您可以使用简单的 varchar 列作为四键并从左到右搜索级别。一个很好的解释来自 Microsoft Bing maps quadkey 网站。

【讨论】:

    【解决方案2】:

    您必须将地球划分为多个区域,然后使用内点算法来确定手机所在的区域。每个可能的区域子集将唯一地确定 100 个最近的节点以达到公平的近似值。您可以通过逐个检查候选节点的距离来获得一组精确的 100 个节点,候选节点(再次)由区域的子集确定。

    【讨论】:

      【解决方案3】:

      已经为您的任务发明了地理空间数据库。
      有 Oracle Spatial(昂贵)和 PostGres(免费)。
      这些数据库将您的数百万个点存储在地理索引、四叉树 (Oracle) 中。 这样的查询几乎不需要时间。

      有些人,比如我,更喜欢把数据库放在一边,自己建立四叉树。

      搜索和插入操作很容易实现。更新/删除可能更复杂。(与实施工作相关的最便宜的是每分钟建立一个新的四叉树)

      使用四叉树,您可以在一秒钟内执行成百上千个最近的 100 个点。

      【讨论】:

      • @eggyal 因为它是一个排序依据。从一百万减少到几个之前必须完成,例如在使用空间扩展的 where 子句中。
      • 我看到提到 MySQL 也有空间扩展的评论已经消失了。所以我再次发布这个,因为我发现它很有价值。
      • 您介意解释一下我如何能“在一秒钟内完成数千个如此接近的 100 点”吗?对于给定的点curr,我现在选择SELECT user_id, GLENGTH(LINESTRINGFROMWKB(LINESTRING(ASBINARY(curr),ASBINARY(pt)))) AS distance ORDER BY distance LIMIT 100 最接近的100 个点,但这实际上很慢。如果我可以添加 WHERE 子句,也许事情会更快,但我看不出有什么办法提前确定最近的 100 个点是在 5 公里范围内,还是在 5000 公里范围内。
      • 问题是你真的想要最近的 100 个点,即使 100 公里内只有 50 个点? (所以距离
      • 恐怕100公里半径在农村地区通常只能产生1-2个点。 1000 公里半径可能包括一半的用户群。关于在内存中构建我自己的树:这可以在 PHP 中以某种方式完成吗?如果没有,我怎样才能让它与我的应用程序的其余部分交互,这些应用程序是在服务器端用 PHP/MySQL 编写的?
      【解决方案4】:

      在架构上,我会安排每个“点”在其位置变化超过一定数量时将其与服务器联系起来。在服务器上,您可以完成计算移动点与其他每个点之间的距离的繁重工作,并为每个其他点更新它们的 100 个最近点列表(如果需要)。然后,您可以在更改发生时将更改推送到最接近的 100 个列表(如果您使用 App Engine,这很简单,支持 Android 推送)。

      这将涉及的工作量降至最低:

      • 仅当点移动足够远时才报告位置变化
      • 仅在收到报告时重新计算距离
      • 不要每次都为一个点重新构建最近的 100 个列表,构建一次列表,然后确定是否要从其他每个点的列表中添加或删除已移动的点。
      • 仅通知其前 100 名列表的更改点以保留带宽。

      您可以使用一些算法来让这个问题变得超级高效,而且这个问题也有一种 fork/join 的感觉,让您可以在问题上投入大量精力。

      【讨论】:

        猜你喜欢
        • 2015-11-27
        • 1970-01-01
        • 2020-11-05
        • 1970-01-01
        • 1970-01-01
        • 2018-02-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多