我是核心开发人员之一ArangoDB
并尝试优化您的查询。因为我没有你的dataset
我只能说说我的测试dataset
如果您能验证我的结果,我会很高兴。
首先,如果我正在跑步ArangoDB
2.7,但在这种特殊情况下,我预计与 2.6 相比不会有重大性能差异。
In my dataset
我可以在大约 7 秒内执行您的查询。
第一个修复:
在你的朋友声明中你使用includeData: true
并且只返回_id
. With 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
(only _ids
)
4. 求交集friends
and foaf_friends
并计算它们
这个查询会像这样:
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。这将进一步提高性能(特别是在有很多边缘的情况下)。
Future
请继续关注我们的下一个版本,我们现在正在向 AQL 添加更多功能,这将使您的案例更容易查询,并且应该会进一步提升性能。