我正在评估ArangoDB,我发现GRAPH_EDGES和GRAPH_VERTICES命令非常慢,小集合(300个顶点)。
我有3个收藏品:
TactiveService(300个顶点) - > TusesCommand(300边) - > Tcommand(1顶点)
使用GRAPH_EDGES,此查询需要 24秒
FOR service IN TactiveService
LET usesCommand = (
return FIRST(GRAPH_EDGES("topvision", {}, { edgeExamples : [{_from: service._id}], edgeCollectionRestriction : "TusesCommand", includeData:true, maxDepth : 1 }))
)
LET command = DOCUMENT(usesCommand[0]._to)
RETURN { service : service, usesCommand: usesCommand[0], command:command}
对于相同的结果,此查询需要 0.020秒
FOR service IN TactiveService
LET usesCommand = (
FOR usesCommand IN TusesCommand
FILTER usesCommand._from == service._id
RETURN usesCommand
)
LET command = DOCUMENT(usesCommand[0]._to)
RETURN { service : service, usesCommand: usesCommand[0], command:command}
GRAPH_EDGES在FOR语句中对我无法使用(与GRAPH_VERTICES相同的问题)。
欢迎这种缓慢的原因的想法。
答案 0 :(得分:3)
我们非常清楚GRAPH_EDGES
不适合在查询中使用。
因此,我们引入了AQL pattern matching traversals,这应该会有更好的表现。
您可以像这样制定您的查询,将GRAPH_EDGES
替换为遍历:
FOR service IN TactiveService
LET usesCommand = (
FOR v, e IN 1..1 OUTBOUND service "TusesCommand"
FILTER e._from == service._id RETURN e
)
LET command = DOCUMENT(usesCommand[0]._to)
RETURN { service : service, usesCommand: usesCommand[0], command:command}
请注意,指定的过滤器含有true
,因为我们从OUTBOUND
开始查询service
个边缘,因此e._from
始终等于service._id
}。我们使用匿名图查询而不是指定GRAPH "topvision"
及稍后限制我们想要在遍历中考虑的边集合,而是仅使用边缘集合TusesCommand
。
如此简化它,查询可能看起来像:
FOR service IN TactiveService
LET usesCommand = (
FOR v, e IN 1..1 OUTBOUND service "TusesCommand" RETURN {v: v, e: e}
)
RETURN { service : service, usesCommand: usesCommand}
这可能会返回比查询更多的顶点,但它只会获取一次;所以结果集可能会更大,但查询的删除DOCUMENT
调用会减少索引查找次数。
正如您已经注意到并使用第二个查询制定的,如果您的实际问题更适合classic join ArangoDB,您可以自由选择使用您的数据。
编辑:迈克尔是对的,方向必须是OUTBOUND
答案 1 :(得分:3)
如果出于某种原因你不想像@dothebart建议的那样升级到2.8。您还可以修复旧查询。 原文:
FOR service IN TactiveService
LET usesCommand = (
return FIRST(GRAPH_EDGES("topvision", {}, { edgeExamples : [{_from: service._id}], edgeCollectionRestriction : "TusesCommand", includeData:true, maxDepth : 1 }))
)
LET command = DOCUMENT(usesCommand[0]._to)
RETURN { service : service, usesCommand: usesCommand[0], command:command}
查询的缓慢部分是找到起点。 GRAPH_EDGES的API使用第二个参数作为起始示例。 {}
与所有起始点匹配。因此,它现在首先计算所有顶点的所有出站边缘(这很昂贵,因为这实际上意味着对于起始集合中的每个顶点,我们收集起始集合中每个顶点的所有边缘)。比它使用您给出的示例过滤所有找到的边缘(其中几乎删除了所有边缘)。
如果用起始顶点的_id替换start示例,它将只收集此特定顶点的边。
现在你也只对一个方向(OUTBOUND)的边缘感兴趣,所以你也可以在选项中给它(因此只有GRAPH_EDGES首先从_from == service._id获取边缘。)
FOR service IN TactiveService
LET usesCommand = (
RETURN FIRST(GRAPH_EDGES("topvision", service._id, { edgeCollectionRestriction : "TusesCommand", includeData:true, maxDepth : 1, direction: 'outbound' }))
)
LET command = DOCUMENT(usesCommand[0]._to)
RETURN { service : service, usesCommand: usesCommand[0], command:command}
但是我仍然期望@dothebart的版本在2.8中更快,我也建议切换到最新版本。