Grails1.1beta2を使用しています。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回のトランザクションの後、それぞれが1分以上かかりますが、これもまた受け入れられません。さらに悪いことに、Grailsは最終的にJavaヒープメモリを使い果たします。OutOfMemoryError
JVMヒープサイズを増やすことはできますが、それは例外を遅らせるだけです。
これがなぜであるかについて何か考えはありますか?いくつかの内部リソースがリリースされていないようなものです。パフォーマンスが悪化し、メモリが保持され、最終的にシステムのメモリが不足します。
Grailsのドキュメントによると、 SpringのオブジェクトwithTransaction
にクロージャーを渡します。トランザクションを終了/終了するためのTransactionStatus
情報が見つかりませんでした。TransactionStatus
編集:これはGrailsのコンソールから実行しています(grails console
)
編集:メモリ不足の例外は次のとおりです。
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)