Hibernate Grails批读优化
我需要使用自定义实现定期从实时遗留数据库中重新索引我的所有域实例 到目前为止,我发现的所有建议都是用于优化批处理写入操作的 许多表都有数十万条记录,如果不是数百万条记录的话,还有Hibernate Grails批读优化,hibernate,grails,gorm,Hibernate,Grails,Gorm,我需要使用自定义实现定期从实时遗留数据库中重新索引我的所有域实例 到目前为止,我发现的所有建议都是用于优化批处理写入操作的 许多表都有数十万条记录,如果不是数百万条记录的话,还有domain.list()的简单解决方案。每个{…}似乎都会立即将整个数据集加载到内存中 使用Hibernate似乎是一个很好的解决方案,但它在级别上工作,并且不会重新创建实际的域对象。我可以将id字段用于实例,但这似乎效率低下 该插件似乎执行了有效的reindex操作 要成功批量读取域实例,还有哪些其他选项或优化 更
domain.list()的简单解决方案。每个{…}
似乎都会立即将整个数据集加载到内存中
使用Hibernate似乎是一个很好的解决方案,但它在级别上工作,并且不会重新创建实际的域对象。我可以将id
字段用于实例,但这似乎效率低下
该插件似乎执行了有效的reindex
操作
要成功批量读取域实例,还有哪些其他选项或优化
更新 最近,我在Grails邮件列表上偶然发现了一个4年前的帖子,其中有一个from,表示使用ScrollableResultSet效率低下。他建议使用标准GORM方法对记录进行分页,并分批清除会话。1)使用传统的Java for循环将为您节省一点开销 2) 对数据进行分块可能会有所帮助。您可以使用max:和offset:来获得100或1000的块,这样您就可以始终处理较小的集: 如果您正在修改该表中的对象,或者在工作流中间添加新数据,则可能会出现此问题。(我将留给您测试:) 3) 使用SQL或HSQL获取所有ID,然后使用Grails.load()也可能有所帮助
4) 我以前尝试过使用Grails/Hibernate实现一些大型批处理作业,但发现它确实不能很好地工作。我建议您尽可能直接使用SQL处理数据库。它将是目前最快的。您可以使用类似于下面的实用程序类来批量手动加载记录
class Paginator {
private static final Logger log = Logger.getLogger("grails.app.Paginator")
int batchSize
int totalCount
public void eachPage(Closure c) {
SessionFactory sessionFactory = Holders.applicationContext.sessionFactory
if(totalCount > 0) {
(0..totalCount -1).step(batchSize) { int offset ->
log.debug "Executing batch $offset to ${offset + batchSize}"
try {
c.call(batchSize, offset)
sessionFactory.currentSession.clear()
}catch(Exception e) {
log.error "Error encountered while executing batch [$offset - ${batchSize + offset}]"
}
}
}
}
}
然后
Paginator p = new Paginator(batchSize:500, totalCount: Domain.count())
p.eachPage {def max, def offset ->
List rows = Domain.list(max:max, offset:offset)
//do some thing with records
}
您可以将paginator与gorm或direct sql或任何东西一起使用。我认为您的想法是正确的,可以滚动查询所有实例id,然后分别加载它们。唯一的问题是带有复合主键的旧表。根据您的DB实现,在重复选择相同数据时,使用偏移量可能会增加大量开销。对于简单的查询来说,这可能不是一个问题,但是对于更复杂的查询,这会增加很多时间。