ArangoDB 中的社交网络查询
Social network-ish query in ArangoDB
我的数据库有以下 "schema":
- 用户 作者 帖子
- 用户 喜欢 帖子
我的小测试数据库包含:
- 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 专家可以审查我的查询并提示一些潜在的性能问题,我将不胜感激。非常感谢!
有几种方法可以使此查询 运行 更快。
最大的改进是将对 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 函数,因此需要重复设置其上下文(与从内部循环调用时一样频繁)。遍历和连接解决方案可以在调用之间保留更多上下文,因此它们是 "cheaper".
我的数据库有以下 "schema":
- 用户 作者 帖子
- 用户 喜欢 帖子
我的小测试数据库包含:
- 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 专家可以审查我的查询并提示一些潜在的性能问题,我将不胜感激。非常感谢!
有几种方法可以使此查询 运行 更快。
最大的改进是将对 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 函数,因此需要重复设置其上下文(与从内部循环调用时一样频繁)。遍历和连接解决方案可以在调用之间保留更多上下文,因此它们是 "cheaper".