我正在评估ArangoDB,我发现GRAPH_EDGES和GRAPH_VERTICES命令非常慢,在小集合上(300个顶点)。
我有3个收藏:
战术服务(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也有同样的问题)。
关于这种缓慢的原因的想法是受欢迎的。
我们很清楚GRAPH_EDGES
不太适合在查询中这样使用。
因此,我们引入了AQL模式匹配遍历,它应该表现得更好。
您可以这样表述查询,用遍历替换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
,因为我们从service
开始查询OUTBOUND
边,所以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
调用,索引查找的次数减少了。
正如您已经注意到的,并在第二个查询中公式化了,如果您的实际问题在经典联接中效果更好,ArangoDB将为您提供使用此类数据的自由选择。
edit:Michael肯定是对的,方向必须是OUTBOUND
如果出于某种原因,您不想像@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,它将只收集该特定顶点的边。现在,您也只对一个方向(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中会更快,我也建议切换到最新版本。