簡體   English   中英

什么是最快的ArangoDB朋友的朋友查詢(有計數)

[英]What is the fastest ArangoDB friends-of-friends query (with count)

我正在嘗試使用ArangoDB來獲取朋友的朋友列表。 不僅僅是一個基本的朋友朋友列表,我還想知道用戶和朋友的朋友有多少朋友,並對結果進行排序。 在多次嘗試(重新)編寫性能最佳的AQL查詢之后,這就是我最終的結果:

LET friends = (
  FOR f IN GRAPH_NEIGHBORS('graph', @user, {"direction": "any", "includeData": true, "edgeExamples": { name: "FRIENDS_WITH"}})
  RETURN f._id
)

LET foafs = (FOR friend IN friends
  FOR foaf in GRAPH_NEIGHBORS('graph', friend, {"direction": "any", "includeData": true, "edgeExamples": { name: "FRIENDS_WITH"}})
    FILTER foaf._id != @user AND foaf._id NOT IN friends
    COLLECT foaf_result = foaf WITH COUNT INTO common_friend_count
    RETURN {
      user: foaf_result,
      common_friend_count: common_friend_count
    }
)
FOR foaf IN foafs
  SORT foaf.common_friend_count DESC
  RETURN foaf

不幸的是,性能並不像我想的那么好。 與同一查詢(和數據)的Neo4j版本相比,AQL似乎相當慢(5-10倍)。

我想知道的是......我如何改進查詢以使其表現更好?

我是ArangoDB的核心開發人員之一,並嘗試優化您的查詢。 由於我沒有您的dataset我只能談論我的測試dataset ,並且很高興聽到您是否可以驗證我的結果。

首先,如果我在ArangoDB 2.7上運行,但在這種特殊情況下,我不認為2.6的主要性能差異。

在我的dataset我可以執行您的查詢,因為它在~7秒內。 第一個修復:在你的朋友聲明中,你使用includeData: true並且只返回_id 使用includeData: false GRAPH_NEIGHBORS直接返回_id ,我們也可以在這里刪除子查詢

LET friends = GRAPH_NEIGHBORS('graph', 
                              @user,
                              {"direction": "any",
                               "edgeExamples": { 
                                   name: "FRIENDS_WITH"
               }})

這使我的機器下降到~1.1秒。 所以我希望這將接近Neo4J的性能。

為什么這會產生很大的影響? 在內部,我們首先找到_id值而不實際加載文檔JSON。 在您的查詢中,您不需要任何此類數據,因此我們可以安全地繼續打開它。

但現在真正改善了

您的查詢采用“邏輯”方式,首先獲取用戶鄰居,而不是找到他們的鄰居,計算找到foaf頻率並對其進行排序。 這必須在內存中構建完整的foaf網絡並將其整體排序。

你也可以用不同的方式做到:1。找到所有用戶的friends (只有_ids )2。查找所有foaf (完整文檔)3。對於每個foaf找到所有foaf_friends (只有_ids )4。找到friends的交集foaf_friends和COUNT他們

這個查詢是這樣的:

LET fids = GRAPH_NEIGHBORS("graph",
                           @user,
                           {
                             "direction":"any",
                             "edgeExamples": {
                               "name": "FRIENDS_WITH"
                              }
                           }
                          )
FOR foaf IN GRAPH_NEIGHBORS("graph",
                            @user,
                            {
                              "minDepth": 2,
                              "maxDepth": 2,
                              "direction": "any",
                              "includeData": true,
                              "edgeExamples": {
                                "name": "FRIENDS_WITH"
                              }
                            }
                           )
  LET commonIds = GRAPH_NEIGHBORS("graph",
                                  foaf._id, {
                                    "direction": "any",
                                    "edgeExamples": {
                                      "name": "FRIENDS_WITH"
                                     }
                                  }
                                 )
  LET common_friend_count = LENGTH(INTERSECTION(fids, commonIds))
  SORT common_friend_count DESC
  RETURN {user: foaf, common_friend_count: common_friend_count}

我的測試圖中的哪個在~0.024秒內執行

所以這給了我250倍的執行時間,我希望它比你在Neo4j中的當前查詢更快,但由於我沒有你的dataset我無法驗證它,如果你能做到並告訴它會很好我。

最后一件事

使用edgeExamples: {name : "FRIENDS_WITH" }它與includeData相同,在這種情況下,我們必須找到真正的邊緣並查看它。 如果根據名稱將邊存儲在單獨的集合中,則可以避免這種情況。 然后刪除edgeExamples。 這將進一步提高性能(特別是如果有很多邊緣)。

未來

請繼續關注我們的下一個版本,我們現在正在為AQL添加更多功能,這將使您的案例更容易查詢,並應該提供另一個性能提升。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM