我的数据库有以下“架构”:
我的适度测试数据库包含:
现在,我想查询最受欢迎的用户,即在所有帖子中收集最多喜欢的用户。我提出了以下问题:
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专家可以查看我的查询并暗示一些潜在的性能问题,我将不胜感激。非常感谢!
答案 0 :(得分:3)
有几种方法可以让这个查询运行得更快。
最能改进的是用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函数,因此需要重复设置其上下文(就像从内循环中调用它一样)。遍历和连接解决方案可以在呼叫之间保持更多的上下文,因此它们更便宜"。