Neo4j 循环性能

Neo4j performance with cycles

我有一个比较大的 neo4j 图,有 700 万个顶点和 500 万个关系。

当我试图找出一个节点的子树大小时,neo4j 被困在遍历 600,000 个节点中,其中只有 130 个是唯一的。 它这样做是因为循环。 看起来它只在遍历整个图到最大深度后才应用 distinct

是否可以通过某种方式改变这种行为?

查询是:

match (a1)-[o1*1..]->(a2) WHERE a1.id = '123' RETURN distinct a2

您可以通过使用 APOC 过程 apoc.periodic.commit 一次迭代地遍历子图 a "layer",同时避免多次重新处理同一节点。该过程迭代地处理一个查询,直到它 returns 0.

这是此技术的一个示例。它:

  • 使用临时 TempNode 节点来跟踪迭代之间的几个重要值,其中一个最终将包含子图中节点的不同 ID("root" 除外节点的 id,因为你的问题的查询也遗漏了它)。
  • 假设您关心的所有节点共享相同的标签 Foo,并且您在 Foo(id) 上有一个索引。这是为了加快 MATCH 操作,并非绝对必要。

第 1 步:创建临时节点(使用 MERGE,重用现有节点,如果有的话)

WITH '123' AS rootId
MERGE (temp:TempNode)
SET temp.allIds = [rootId], temp.layerIds = [rootId];

第 2 步:执行迭代(获取所有子图节点)

CALL apoc.periodic.commit("
  MATCH (temp:TempNode)
  UNWIND temp.layerIds AS id
  MATCH (n:Foo) WHERE n.id = id
  OPTIONAL MATCH (n)-->(next)
  WHERE NOT next.id IN temp.allIds
  WITH temp, COLLECT(DISTINCT next.id) AS layerIds
  SET temp.allIds = temp.allIds + layerIds, temp.layerIds = layerIds
  RETURN SIZE(layerIds);
");

第 3 步:使用子图 ID

MATCH (temp:TempNode)
// ... use temp.allIds, which contains the distinct ids in the subgraph ...