【翻译自:https://neo4j.com/developer/kb/large-delete-transaction-best-practices-in-neo4j/ 】
【由Neo4j APAC授权编译发布】
在处理大型删除操作时,为了获得最佳性能,避免对系统产生负面影响,请参考本文的最佳实践。
首先确定您的需求:
1)如果想重新创建,则删除整个图数据库;
2)删除图中的很大一部分,或者删除MATCH语句查询的大量节点/关系;
根据具体情况,我们会有不同的建议。
目前,删除整个图数据库的最佳方法是先停止数据库,重命名或者删除图存储目录(data/graph.db(v3.x前版本)或data/databases/graph.db(V3.x后版本)),然后启动数据库,系统将新建空的数据库。
如果您想从图中删除大量对象,请注意创建的单个事务不要过大,避免遇到Java堆溢出错误。参考以下示例,以批量方式删除匹配记录的子集,直到完全删除为止:
V3.x以后版本使用APOC方式:
call apoc.periodic.iterate("MATCH (n:Foo) where n.foo='bar' return n", "DETACH DELETE n", {batchSize:10000})
yield batches, total return batches, total
V3.x以前版本:
// 查询您要删除的节点
MATCH (n:Foo) where n.foo = 'bar'// 获取10K的节点和关系 (如果每个平均超过100节点/关系,则降低此数)
WITH n LIMIT 10000
DETACH DELETE n
RETURN count(*);
执行此查询,直到语句返回0(零)记录。
对于Neo4j 2.3之前的版本,请运行:
// 查询您要删除的节点
MATCH (n:Foo) where n.foo = 'bar'// 获取10K的节点和关系 (如果每个平均超过100节点/关系,则降低此数)
WITH n LIMIT 10000
MATCH (n)-[r]-()
DELETE n,r
RETURN count(*);
在所有示例中,我们都将批量删除10k。如果符合删除条件的节点有大量的关系,这可能仍会导致堆溢出错误。例如,如果要删除的节点为一百万个 :FOLLOWS 关系,则此节点将执行删除此节点及其一百万个 :FOLLOWS 关系。
另外, 知识库文档 删除密集节点时如何避免使用过多内存【https://neo4j.com/developer/kb/how-to-bulk-delete-dense-nodes/】也提到相关问题。
假如您想要删除一批节点(根据规则还需要删除它们之间的关系),执行 DETACH DELETE 完成该操作非常方便。但是,如果节点密集,或者每批中有大量节点有成千上万的关系,该操作会有问题,“batch size” 很快会超出您的预期。
APOC允许我们按下面的方式执行。事实上,我们想要找到要删除的节点集,并将其传递给 apoc.periodic.commit ,按照前10K关系,然后下一10K的关系对删除进行批处理,以此类推,直到完成。下面的Cypher语句查询节点的 ttl 属性在当前时间之前并且标签为 :TTL 的节点集,传给periodic commit执行,批量删除10K,此语句在大量节点集上运行良好。
MATCH (n:TTL)
WHERE n.ttl < timestamp()
WITH collect(n) AS nn
CALL apoc.periodic.commit("
UNWIND $nodes AS n
WITH sum(size((n)--())) AS count_remaining, collect(n) AS nn
UNWIND nn AS n
OPTIONAL MATCH (n)-[r]-()
WITH n, r, count_remaining
LIMIT $limit
DELETE r
RETURN count_remaining
", {limit:10000, nodes:nn}) yield updates, executions, runtime, batches, failedBatches, batchErrors, failedCommits, commitErrors
UNWIND nn AS n
DELETE n
RETURN updates, executions, runtime, batches
更多技术咨询:
Email:yusonglin@we-yun.com
网友评论