ArangoDB:GRAPH_EDGES 命令在小型集合上非常慢(超过 20 秒)
ArangoDB: GRAPH_EDGES command very slow (more than 20 sec) on small collections
我正在评估 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 相同的问题)。
欢迎就这种缓慢的原因提出想法。
我们很清楚 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
因为我们查询了从 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}
这可能比您的查询多 return 个顶点,但它只会获取一次;因此结果集可能会更大,但索引查找的数量会因删除的 DOCUMENT
查询调用而减少。
正如您已经注意到并在第二个查询中制定的那样,如果您的实际问题使用 classic join ArangoDB 可以让您自由选择如何处理您的数据。
edit: 迈克尔说得对,方向必须是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 使用第二个参数作为开始示例。 {}
匹配所有起点。所以它现在首先计算所有顶点的所有出站边(这很昂贵,因为这实际上意味着对于起始集合中的每个顶点,我们收集起始集合中每个顶点的所有边)。比它 post 使用您提供的示例过滤所有找到的边缘(这再次删除了几乎所有边缘)。
如果您用起始顶点的 _id 替换起始示例,它将只收集该特定顶点的边。
现在你也只对一个方向的边缘(OUTBOUND)感兴趣,所以你也可以在选项中给出它(所以只有带有 _from == service._id 的边缘首先被 GRAPH_EDGES 获取).
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 中更快,我也建议切换到最新版本。
我正在评估 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 相同的问题)。
欢迎就这种缓慢的原因提出想法。
我们很清楚 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
因为我们查询了从 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}
这可能比您的查询多 return 个顶点,但它只会获取一次;因此结果集可能会更大,但索引查找的数量会因删除的 DOCUMENT
查询调用而减少。
正如您已经注意到并在第二个查询中制定的那样,如果您的实际问题使用 classic join ArangoDB 可以让您自由选择如何处理您的数据。
edit: 迈克尔说得对,方向必须是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 使用第二个参数作为开始示例。 {}
匹配所有起点。所以它现在首先计算所有顶点的所有出站边(这很昂贵,因为这实际上意味着对于起始集合中的每个顶点,我们收集起始集合中每个顶点的所有边)。比它 post 使用您提供的示例过滤所有找到的边缘(这再次删除了几乎所有边缘)。
如果您用起始顶点的 _id 替换起始示例,它将只收集该特定顶点的边。
现在你也只对一个方向的边缘(OUTBOUND)感兴趣,所以你也可以在选项中给出它(所以只有带有 _from == service._id 的边缘首先被 GRAPH_EDGES 获取).
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 中更快,我也建议切换到最新版本。