我正在使用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文档,withTransaction
将闭包传递给Spring的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)
这是所有hibernate应用程序的常见问题,它是由hibernate会话的增长引起的。我猜想grails控制台会为您打开一个hibernate会话,其方式类似于我知道它用于普通Web请求的“视图中打开会话”模式。
解决方案是掌握当前会话,并在每次批处理后清除它。我不确定如何使用控制台来获取spring
bean,通常对于控制器或服务,只需将它们声明为成员即可。然后,您可以使用获取当前会话sessionFactory.getCurrentSession()
。为了清除它,只需调用session.clear()
,或者session.evict(Object)
对每个Person
对象有选择地使用。
对于控制器/服务:
class FooController {
def sessionFactory
def doStuff = {
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()
}
// clear session here.
sessionFactory.getCurrentSession().clear();
}
}
// Save any remaining
for (Person p: batch)
p.save()
}
}
}
希望这可以帮助。
问题内容: 我读到这里:使用Python将CSV文件导入sqlite3数据库表 似乎每个人都建议使用逐行读取,而不是使用SQLite的bulk .import。但是,如果您有数百万行的数据,这将使插入速度非常慢。还有其他方法可以避免这种情况吗? 更新:我尝试下面的代码逐行插入,但是速度不如我预期的那样。反正有改进的地方吗 问题答案: 使用生成器表达式将您的数据即时划分为多个块,在事务内进行插入。这
我正在创建一个int数组SecretNumber。当我将数组大小声明为数字时,没有越界异常,但当我用变量(numDigits)声明数组大小时,在索引0处得到行“secretNumber[I]=val”的越界异常。这是类: 这是执行这些方法的主体,我在设置数组之前运行numDigits setter: 如果我设置了NumDigits,为什么索引0会超出界限??
我创建了一个向MySql数据库插入数百万个值的程序。我读到过有关批插入的文章,它将优化我的程序并使其更快,但当我尝试这样做时,它以同样的方式工作。我没有将每个值插入数据库,而是每次将500个值保存在一个列表中,然后将它们插入一个大循环中,如下所示: 然后我删除列表中的所有值,并再次开始收集500个值。它不应该工作得更好吗? 我的插入代码是: 我有一些问题: 1。为什么当我批量插入时它不能更快地工作
我在我的Tomcat/Java应用程序中有一个解析代码的GroovyShell实例。解析非常慢,100行大约1秒。在分析应用程序时,我注意到解析抛出了大量java.lang.ClassNotFoundException异常。我想有什么东西在吞噬它们,因为我在原木的任何地方都没有看到它们。由于脚本使用了大量主应用程序的类,所以我假设这就是导致应用程序变慢的原因。 有没有办法让我捕捉那些异常并获取它们
首先是一些背景知识:我正在使用Spring Security的修改版本来执行Active Directory身份验证,并检查存储在数据库中的可能访问权限。这意味着在普通的Groovy类中有一个调用来从数据库中加载信息: 这在Hibernate 4.3.6.1和Tomcat 7.0.54上效果很好,但是,在升级(升级到4.3.10.18和8.0.14.1)后,它现在在调用动态查找器方法时会产生“Hi
websocket会实时发送大量数据时,我目前写的这些代码,会导致页面卡顿,性能优化我不知道怎么下手了,求大佬指教一下, 有偿。谢谢大佬们