我有一个图形数据集,其中包含大量相对较小的不相交图。我需要从匹配某些搜索条件的一组顶点中找到所有可达的顶点。我使用以下查询:
FOR startnode IN nodes
FILTER startnode._key IN [...set of values...]
FOR node IN 0..100000 OUTBOUND startnode edges
COLLECT k = node._key
RETURN k
即使返回正确的结果,查询也非常慢。这是因为Arango实际上最终会遍历相同的子图多次。例如,说有以下子图:
a -> b -> c -> d -> e
当通过过滤条件选择顶点a和c时,Arango最终从a和c开始进行两个独立的遍历。它在这两个遍历中都访问顶点d和e,这浪费了时间。添加uniqueVertices选项无济于事,因为不会在不同的遍历之间检查顶点的唯一性。
为了确认对性能的影响,我创建了一个额外的根文档,并添加了指向它的链接到我的过滤器找到的所有文档的链接:
FOR startnode IN nodes
FILTER startnode._key IN [...set of values...]
INSERT { _from: 'fakeVertices/0', _to: startnode._id } IN fakeEdges
现在,以下查询比原始查询运行速度快4倍,同时产生相同的结果:
FOR node IN 1..1000000 OUTBOUND 'fakeVertices/0' edges, fakeEdges
OPTIONS { uniqueVertices: 'global', bfs: true }
COLLECT k = node._key
RETURN k
不幸的是,我无法为所有查询创建伪造的顶点/边缘,因为创建它需要更多时间。
我的问题是:Arango是否提供一种方法来确保在给定查询中所有遍历中访问的顶点都是唯一的?如果没有,是否有更好的方法来解决上述问题?
据我了解,这是uniqueVertices
选项的用途,但是对于FOR ...
语句的每次迭代,它都认为从that开始节点遍历的顶点是唯一的。它不知道FOR ...
语句中其他节点上发生的其他遍历。似乎您每次都会遍历许多点,并且这种情况发生在每个新的起始节点上。
只需将其扔在墙上以查看其是否粘住,但是将两个查询组合在一起并在原件上添加OPTIONS
怎么办?
FOR startnode IN nodes
FILTER startnode._key IN [...set of values...]
FOR node IN 0..100000 OUTBOUND startnode edges
OPTIONS { uniqueVertices: 'global', bfs: true }
COLLECT k = node._key
RETURN k
此外,我会高度建议使用named graph,而不是指定边缘集合。