这听起来像你需要 BFS http://en.wikipedia.org/wiki/Breadth-first_search
在线方法:
我认为它可能会很昂贵,具体取决于您要如何使用它。在最坏的情况下,您将迭代数据库中的所有数据:成本运行时O(n)
(假设您有一个查找函数可以在运行时在图中找到用户O(1)
)。
离线方法
您可以进行离线预定预计算并将距离存储为查找函数,但它需要一些额外的内存O(n*n)
,其中 n 是用户数。查找功能的成本现在只是O(1)
或O(logn)
取决于您如何实现它
(忽略我认为将在该区域内的离线运行O(n)
时O(n*n)
)。
策略
您要遵循的策略可能取决于您可以预期的用户数量上限以及用户之间的连接程度。如果您的用户很少,在线方法可能会很好,如果您有数百万用户,那么您可能需要离线方法,但这会花费您一些内存。
其他注意事项
- 线上线下相结合
- 使用缓存策略
- 每当为用户更新新参考时,更新距离查找函数
更新的答案有 17 个 mio。用户,我们将需要离线方法。
我会关注离线版本。您应该避免O(n*n)
我认为可能的运行时。
数据库模型
您应该考虑如何对数据库进行建模,因为这将是此实现中最昂贵的部分。
可能是这样的:为每个用户创建一个表(表名可以是 userId)。每个表都有每个用户的条目(记录键是 userId)。这将导致 17 mio。有 17 米奥的桌子。每个条目(这是O(n*n)
成本)。
离线运行一次 BFS,同时跟踪您访问过的用户以及您在 BFS 迭代中处于哪个级别,并保存与数据库的距离。我还没有考虑过这部分,但我认为这个策略是可行的。请记住在每个节点上运行 BFS,即,直到您访问了所有用户。如果此策略不可行,那么您可以从运行时的每个节点运行 BFS O(n*n)
。这意味着在最坏的情况下运行可能需要一个月的时间,即您的距离数据可能是旧的。运行速度取决于您的用户的连接程度。
或者,如果可能,您可以采用“每当为用户更新新参考时,更新距离查找功能”的方法。这将运行一次 BFS O(n)
,即几秒钟。在第一次事件时调用 BFS(userId),然后在参考更新时调用。
在线您使用 userId 按表名获取表,并通过另一个 userId 获取条目以获取距离。