我正在使用 Grails 1.1 beta2。我需要将大量数据导入到我的 Grails 应用程序中。如果我重复实例化一个 grails 域类然后保存它,性能会慢得令人无法接受。以从电话簿导入人员为例:
for (each person in legacy phone book) {
// Construct new Grails domain class from legacy phone book person
Person person = new Person(...)
person.save()
}
事实证明这速度慢得令人痛苦。 Grails 邮件列表中的某人建议在事务中批量保存。所以现在我有:
List batch = new ArrayList()
for (each person in legacy phone book) {
// Construct new Grails domain class from legacy phone book person
Person person = new Person(...)
batch.add(person)
if (batch.size() > 500) {
Person.withTransaction {
for (Person p: batch)
p.save()
batch.clear()
}
}
}
// Save any remaining
for (Person p: batch)
p.save()
这个工作必须更快,至少在最初是这样。每笔交易保存500条记录。随着时间的推移,交易时间越来越长。前几笔交易大约需要 5 秒,然后它就会从那里开始慢慢蔓延。大约 100 笔交易后,每笔交易都需要一分钟以上,这再次令人无法接受。更糟糕的是,Grails 最终会耗尽 Java 堆内存。我可以增加 JVM 堆大小,但这只会延迟OutOfMemoryError
例外。
有什么想法吗?好像有一些内部资源没有被释放。性能变得更差,内存被占用,然后最终系统耗尽内存。
根据Grails 文档 http://grails.org/doc/1.0.x/ref/Domain%20Classes/withTransaction.html, withTransaction
将闭包传递给 Spring 的TransactionStatus
目的。我找不到任何东西TransactionStatus
关闭/结束交易。
Edit:我从 Grails 控制台运行这个(grails console
)
Edit:这是内存不足的异常:
Exception thrown: Java heap space
java.lang.OutOfMemoryError: Java heap space
at org.hibernate.util.IdentityMap.entryArray(IdentityMap.java:194)
at org.hibernate.util.IdentityMap.concurrentEntries(IdentityMap.java:59)
at org.hibernate.event.def.AbstractFlushingEventListener.prepareEntityFlushes(AbstractFlushingEventListener.java:113)
at org.hibernate.event.def.AbstractFlushingEventListener.flushEverythingToExecutions(AbstractFlushingEventListener.java:65)
at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:26)
at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1000)
at org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:338)
at org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:106)
at org.springframework.orm.hibernate3.HibernateTransactionManager.doCommit(HibernateTransactionManager.java:655)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:732)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:701)
at org.springframework.transaction.support.TransactionTemplate.execute(TransactionTemplate.java:140)