Neo4j MATCH 然后 MERGE 太多数据库命中

Neo4j MATCH then MERGE too many DB hits

这是查询:

MATCH (n:Client{curp:'SOME_VALUE'}) 
WITH n 
MATCH (n)-[:HIZO]-()-[r:FB]-()-[:HIZO]-(m:Client) 
WHERE ID(n)<>ID(m)
AND NOT (m)-[:FB]->(n) 
MERGE (n)-[:FB]->(m) RETURN m.curp

如果查询已经缩小,为什么 Merge 阶段会获得如此多的数据库命中 n, m 对到 6,781 行?

该阶段的详细信息显示:

n, m, r
(n)-[ UNNAMED155:FB]->(m)

请记住,查询会构建行,并且查询中的操作会在构建的每一行上得到 运行。

因为您的匹配中的模式可能会找到指向同一个 :Client 的多条路径,它会建立多行具有相同的 n 和 m(但可能不同的 r,但因为您没有在其他任何地方使用 r你的查询,我鼓励你删除变量)。

这意味着即使您打算 MERGE n 和不同的 m 之间的单一关系,此 MERGE 操作实际上对于 n 和 m 的每个重复行都是 运行。其中一个 MERGE 将创建关系,其他 MERGE 将浪费循环匹配已创建的关系而不做任何其他事情。

这就是为什么我们应该能够通过在执行 MERGE 之前仅考虑不同的 n 和 m 对来降低数据库命中率。

此外,由于您的查询确保我们只考虑不存在关系的 n 和 m,我们可以安全地使用 CREATE 而不是 MERGE,并且它应该会为我们节省一些数据库命中,因为 MERGE 总是尝试MATCH 首先,这是没有必要的。

改进后的查询可能如下所示:

MATCH (n:Client{curp:'SOME_VALUE'}) 
WITH n 
MATCH (n)-[:HIZO]-()-[:FB]-()-[:HIZO]-(m:Client) 
WHERE n <> m
AND NOT (m)-[:FB]->(n) 
WITH DISTINCT n, m
MERGE (n)-[:FB]->(m) 
RETURN m.curp

编辑

返回查询以对 :FB 关系使用 MERGE,因为使用 CREATE 的尝试最终性能不佳。