我正在使用嵌入式Neo4j 2.1.2数据库,并且在以较小批量大小提交的单个事务中创建大量关系或节点时会遇到内存问题。应该/必须避免使用单个长时间运行的事务吗?我原本期望内存使用量会随着提交批量大小而增长。
您可以使用以下简单代码重现错误:
try (Transaction tx = db.beginTx()) {
for (int idx=1; idx<=amount; idx++) {
if (idx % 10000 == 0) {
tx.success();
}
Node n = db.createNode();
}
tx.success();
}
在插入了580.000个节点,堆大小为512MB后,我得到一个OutOfMemoryError。使用的VM标志是:-server -Xmx512m -XX:+UseConcMarkSweepGC
如果我修改代码以便为每个批次使用新的交易,那么它的工作正常且非常快:
Transaction tx = db.beginTx();
try {
for (int idx=1; idx<=amount; idx++) {
if (idx % 10000 == 0) {
tx.success();
tx.close();
tx = db.beginTx();
}
Node n = db.createNode();
}
tx.success();
} finally {
tx.close();
}
答案 0 :(得分:0)
我的猜测是,对节点的引用会保留在堆上,因为它们位于事务中,并且必须保留以用于回滚目的,因此在580 000个节点之后会耗尽内存。如果您以小批量大小运行相同的代码,只要批量大小不超过580 000,这应该可以解决您的问题。
至于你的第二个问题:分配了Java堆内存,但是当你的程序需要更多时,不能动态增加
你需要触发void close(),否则它不会释放资源。
http://api.neo4j.org/current/org/neo4j/graphdb/Transaction.html#close() 提交或标记此事务以进行回滚,具体取决于先前是否已调用success()或failure()。
我认为这个问题是重复的: