【问题标题】:Social network-ish query in ArangoDBArangoDB 中的社交网络查询
【发布时间】:2016-04-02 09:11:08
【问题描述】:

我的数据库有以下“模式”:

  • 用户 作者 帖子
  • 用户 喜欢 帖子

我的测试数据库包含:

  • 162 个用户
  • 442 个帖子
  • 159 个赞

现在我想查询最受欢迎的用户,即在所有帖子中获得最多赞的用户。我想出了以下查询:

FOR u IN users
    LET nblikes = SUM(FOR post IN 1 OUTBOUND u isAuthor
        RETURN LENGTH(GRAPH_EDGES('my-graph', post, { edgeCollectionRestriction: 'likes' })))
    SORT nblikes DESC
    RETURN {
        "username": u.username,
        "nblikes": nblikes
    }

在我的 2014 年中 MacBookPro(2.8GHz Core i7,16GB RAM)上执行大约需要 0.8 秒。 0.8s 并不可耻,但在这么小的数据集上,考虑到 AFAIK,这一切都发生在内存中,我本以为会更好。

如果有一些 ArangoDB 专家可以查看我的查询并提示一些潜在的性能问题,我将不胜感激。非常感谢!

【问题讨论】:

  • 如果您使用建议的图遍历,您的查询速度有多快,使用连接的速度有多快?谢谢!

标签: arangodb


【解决方案1】:

有几种方法可以让这个查询运行得更快。

最大的改进是将GRAPH_EDGES的内部调用替换为另一个深度为1的遍历以找到“likers”,如下所示:

FOR u IN users 
  LET nblikes = SUM(
    FOR post IN 1 OUTBOUND u isAuthor 
      RETURN LENGTH(
        /* the following traversal replaces the call to GRAPH_EDGES */
        FOR liker IN 1 INBOUND post._id likes 
          RETURN 1
      )
  )
  SORT nblikes DESC
  RETURN { 
    username: u.username, 
    nblikes: nblikes
  }

GRAPH_EDGES的内部函数调用非常昂贵,去掉它会大大缩短查询执行时间。

另一种变体是将(现在)两个遍历替换为这样的普通连接:

FOR u IN users 
  LET nblikes = SUM(
    /* the following join between users, isAuthor and likes 
       replaces the traversal & GRAPH_EDGES calls */
    FOR a IN isAuthor 
      FILTER a._from == u._id 
      FOR l IN likes 
        FILTER l._to == a._to 
        RETURN 1
  ) 
  SORT nblikes DESC
  RETURN { 
    username: u.username, 
    nblikes: nblikes
  }

这两种变体都应该比初始查询更快,主要是因为GRAPH_EDGES 在循环中调用的开销很大。由于它是一个无状态的 AQL 函数,因此需要反复设置其上下文(就像从内部循环调用它一样频繁)。遍历和连接解决方​​案可以在调用之间保留更多上下文,因此它们“更便宜”。

【讨论】:

  • 您可以使用GRAPH_EDGES 作为顶级构造,而不是在循环中。如果你想将它与LIMIT 结合起来,一个明确的计数器指标是没有意义的。
猜你喜欢
  • 2016-05-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-12-15
  • 2015-05-15
  • 1970-01-01
相关资源
最近更新 更多