我在一台32GB内存的服务器上运行Neo4J,社区版v2.3.2,配置为使用8GB作为页面缓存,18GB作为堆,另外6GB作为操作系统(根据我对Neo4J的理解,这主要适用于页面缓存索引文件)。
我的数据库有大约250M人员节点和1B关系,我正在运行以下查询来删除一些节点:
MATCH (p:Person)
WHERE NOT HAS (p.fullname)
OPTIONAL MATCH (prev:Person {fullname: p.fname +' '+p.lname})
WHERE prev IS NOT NULL
WITH p LIMIT 100000
DETACH DELETE p
我一直在玩这个以使其实际工作而不会占用所有内存并使服务器崩溃。我必须说我有点失望,我一次只能删除100K节点。预期会有几百万,但这可能是针对不同的问题。
我经常收到以下错误:
ERROR (-v for expanded information):
TransactionFailureException: Transaction was marked as successful, but unable to commit transaction so rolled back.
org.neo4j.graphdb.TransactionFailureException: Transaction was marked as successful, but unable to commit transaction so rolled back.
at org.neo4j.kernel.TopLevelTransaction.close(TopLevelTransaction.java:121)
at org.neo4j.shell.kernel.apps.TransactionProvidingApp.execute(TransactionProvidingApp.java:263)
at ...
Caused by: org.neo4j.kernel.impl.store.InvalidRecordException: RelationshipRecord[250054319] not in use
at org.neo4j.kernel.impl.store.RelationshipStore.fillRecord(RelationshipStore.java:135)
at org.neo4j.kernel.impl.store.RelationshipStore.getRecord(RelationshipStore.java:93)
at org.neo4j.kernel.impl.store.RelationshipStore.getRecord(RelationshipStore.java:88)
at org.neo4j.kernel.impl.transaction.state.Loaders$3.load(Loaders.java:139)
at ...
我找不到与250054319
的ID有任何关系。我可以找到一个带有该ID的节点,但我不确定它与我的查询有什么关系,因为它不满足我的初始条件(NOT HAS p.fullname
)。
我很困惑。有谁知道这个错误?它是什么意思,我该怎么做才能解决它?
也许有帮助说我将此删除作为一次性任务运行,因此可以通过创造性的方式运行此查询。
另一件可能有帮助的事情是,即使在使用LIMIT子句打破查询后,我也遇到了很多内存问题。服务器挂起,崩溃或进入恒定的GC周期,直到我能够找到允许它稍微工作的配置,直到我开始遇到这个问题。
谢谢!
答案 0 :(得分:0)
我有2条评论:
您的查询没有按预期执行。它将删除所有 Person
个没有fullname
属性的节点,即使没有匹配的prev
节点也是如此。这是因为OPTIONAL MATCH
子句(以及后续WHERE
)不必匹配,以便查询继续执行DELETE
子句。
您可能会遇到很多错误,因为DETACH DELETE p
会尝试删除每个p
的所有关系,即使这些关系中的任何关系已被删除。例如,如果2个人之间存在关系,则尝试DETACH DELETE
第二个人会导致错误。
这是一个可以解决这两个问题的查询:
MATCH (p:Person)
WHERE NOT HAS (p.fullname)
OPTIONAL MATCH (prev:Person { fullname: p.fname +' '+p.lname })
WITH CASE WHEN prev IS NOT NULL THEN p ELSE NULL END AS delP
LIMIT 100000
OPTIONAL MATCH (delP)-[r]-()
WITH COLLECT(delP) AS ps, COLLECT(DISTINCT r) AS rels
FOREACH (r IN rels | DELETE r)
FOREACH (p IN ps | DELETE p)