Graph ArangoDb中的缩放图遍历

Graph ArangoDb中的缩放图遍历,graph,graph-databases,arangodb,Graph,Graph Databases,Arangodb,我有一个树状结构,实际上是一个有向无环图。小版本如下所示。 在任何父级,我都希望对子树的一些属性求和。今天,我在AQL中使用基于起始节点的遍历和收集来完成这项工作: for c in traversal(nodes,nodeTree,ch,'inbound',{uniqueness:{vertices:'global'}}) collect child = ch._id into group 然后我可以在组上使用聚合。(对于Arangodb2.8,我相信现在可以直接在collect语

我有一个树状结构,实际上是一个有向无环图。小版本如下所示。

在任何父级,我都希望对子树的一些属性求和。今天,我在AQL中使用基于起始节点的遍历和收集来完成这项工作:

for c in traversal(nodes,nodeTree,ch,'inbound',{uniqueness:{vertices:'global'}})
    collect child = ch._id into group
然后我可以在组上使用聚合。(对于Arangodb2.8,我相信现在可以直接在collect语句中完成这项工作。)唯一性选项解决了重复的问题

缩放

当树(图)增长到相当大的规模(10-20k个节点)时,这种规模将如何?我需要它是快速的,因为用户将等待响应(不是一个长时间运行的作业)

我正在考虑在节点中缓存值并使用脏标志。然后在节点1中,如果2和3都是干净的,则它们可以求和。问题是2和3的和中都包含了5

我怎样才能解决这个问题?或者这不是问题——遍历真的那么快吗


到目前为止,我已经想到了让每个节点包含一个它的子树副本列表的想法,在1的情况下,这意味着信息“5被包含两次”。这可以用来从1的总数中减去。但是我怎么才能找到这些信息呢?我曾考虑过找到所有父节点大于1的节点,然后向上遍历(这很快),然后以某种方式计算此信息。

遍历的运行时间受过程中实际接触的顶点和边的数量限制。因此,遍历的运行时间取决于路径的深度和分支因子(预期有多少个具有多个父节点的顶点)

您描述的构造存在的问题是,遍历将从
1
5
(假设是左一个)选择一条路径,并对所有值求和,最终返回到
1
以选择正确的路径。现在它再次到达
5
,但这次搜索深度低于上次看到
5
,因此它必须再次实际遍历5上的子树,因为它现在可能在该路径中获得更大的距离(它不知道该子树上的所有顶点都可以在更短的距离内到达)。此路径上的顶点不会再次调用访问者,但仍会被遍历和跟随,这需要花费时间

我试图优化遍历以验证伸缩性。 首先,我注册了一个新的优化访问者:

require("@arangodb/aql/functions").register("test::counter", "function (config, result, vertex) {result[0] = result[0] || {value: 0}; result[0].value += vertex.value}");
该访问者将顶点的值相加并直接返回它们,因此我可以去掉
COLLECT
语句。我可以用它作为我的AQL:

FOR x IN TRAVERSAL(TestVertices, TestEdges, 'TestVertices/0', 'outbound', {uniqueness:{vertices:'global'}, visitor: 'test::counter', maxDepth: 5012})
  RETURN x.value
注意:我已经在选项中给出了一个
maxDepth
,用于实际进行高深度搜索,默认值为
256

我的测试树基本上是一个由
20.000
个顶点组成的链,其中每个第三个顶点都有一条额外的边来连接链中稍后的一个随机顶点(模拟您描述的多父问题)

通过这次遍历,我设法在
~5秒内从根目录中搜索
5012
。使用更高的深度,它会呈指数增长

我假设您的图形具有较少的这些多个父对象,因此我希望您的图形上的运行时更少

如果你期望更多的读,那么你也可以考虑计算每个写的总和。 这将减慢写入速度,但会使所有读取瞬间完成

例如,在更新值时,您还可以使用以下AQL:

LET i = (FOR x IN 1..5012 INBOUND @start TestEdges
           RETURN DISTINCT x) 
  FOR x IN i UPDATE x WITH {sum: x.sum + @add} IN TestVertices
使用要添加的值的绑定参数
@add
,以及更新的顶点的绑定参数
@start
。使用此技术,您的读取查询非常简单:

FOR x IN TestVertices FILTER x._id == @start 
  RETURN x.sum

希望这能有所帮助。

谢谢你的全面回答。看起来遍历速度相当快。在我的例子中,图表很可能是宽的而不是深的。我想说的是MaxDepth 50。我绝对希望读的比写的多,这就是为什么我考虑缓存总和,就像你举的一个例子。这里我关心的是1)一个“热”根(针对每个写块等进行访问)和2)确信总和保持正确(一个事务可能会有帮助)2)对于正确性,您可以在foxx应用程序中为多个AQL查询实现事务()1)是的,您是对的“热”根可能会阻塞,但我会尝试一下,看看模拟数据(甚至是真实数据)的性能,看看它是否真的有问题。写入速度可能足以让用户感觉到“无阻塞”,因为实际读取总是一个恒定的时间动作。因此,相比之下,使用阻塞根目录的用户的平均等待时间可能更低?现在已经没有访问者函数了(使用新的遍历语法)?看起来
collect aggregate
很好地解决了这个问题。