我有一个拥有约250M节点的Neo4J数据库(社区版,v2.3.2),我需要运行一个查询来迭代所有节点并更新属性。它不是我常规查询的一部分,而是我必须运行的一次性维护任务。
我可以用Cypher轻松表达它,但看起来Neo4J试图在内存中保留所有节点,然后执行我的SET操作,导致内存耗尽,甚至更糟 - 将整个JVM放入常量GC循环。我有可能让它在foreach循环中运行,一次在一个节点上运行吗?
我的Cypher查询将是:
MATCH (n:MyNode) WHERE NOT HAS (n.newColumn) SET n.newColumn=n.c1+n.c2
我不介意它是否会运行很长时间,只是它不会让服务器本身崩溃。如果Cypher不是完成任务的最佳工具,我也可以使用其他API。
更一般地说 - 当您需要运行"全图扫描"时,最佳做法是什么?查询您的Neo4J数据库?
谢谢!
答案 0 :(得分:6)
这将导致一个巨大的事务,需要先在内存中建立,然后在提交时刷新到光盘。
这里的最佳做法是limit
事务的范围并多次调用该语句:
MATCH (n:MyNode)
WHERE NOT HAS (n.newColumn)
WITH n LIMIT 10000
SET n.newColumn=n.c1+n.c2
RETURN count(n)
运行此语句,直到返回结果为止。
要自动执行此过程,您可以使用apoc
procedures和apoc.periodic.iterate()
这样的<{p}}
call apoc.periodic.iterate(
'MATCH (n:MyNode) WHERE NOT exists(n.newColumn) RETURN n',
'SET n.newColumn=n.c1+n.c2', {batchSize:10000,iterateList:true,parallel:true}
);