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 的尝试最终性能不佳。
这是查询:
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 的尝试最终性能不佳。