[英]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.