我正在处理大型csv文件,我发现了有关批量导入的文章:http://naleid.com/blog/2009/10/01/batch-import-performance-with-grails-and-mysql/。我也尝试过这样做,但似乎没有效果。
每次刷新后是否可以在数据库中查看实例?因为现在当我尝试查询' SELECT COUNT(*)FROM TABLE1'时,现在有0个或所有的entite,所以它看起来像是一次性提交实例。
然后我还注意到,第一次导入空白表时导入工作很快,但是当表已满并且实体应该更新或保存为新实体时,整个过程非常慢。这主要是因为内存未被清理并减少到1MB或更少而且应用程序卡住了。那是因为没有刷新会话吗?
我的导入代码在这里:
public void saveAll(List<MedicalInstrument> listMedicalInstruments) {
log.info("start saving")
for (int i = 0; i < listMedicalInstruments.size() - 1; i++) {
def medicalInstrument = listMedicalInstruments.get(i)
def persistedMedicalInstrument = MedicalInstrument.findByCode(medicalInstrument.code)
if (persistedMedicalInstrument) {
persistedMedicalInstrument.properties = medicalInstrument.properties
persistedMedicalInstrument.save()
} else {
medicalInstrument.save()
}
if ((i + 1) % 100 == 0) {
cleanUpGorm()
if ((i + 1) % 1000 == 0) {
log.info("saved ${i} entities")
}
}
}
cleanUpGorm()
}
protected void cleanUpGorm() {
log.info("cleanin GORM")
def session = sessionFactory.currentSession
session.flush()
session.clear()
propertyInstanceMap.get().clear()
}
非常感谢您的帮助!
此致
Lojza
P.S。:我的JVM内存总共有252.81 MB,但它只是我和其他3人的测试环境。
答案 0 :(得分:6)
我曾遇到过类似的问题。然后我意识到原因是因为我在grails服务中这样做,默认情况下是事务性的。因此,对服务中的方法的每次调用本身都包含在一个事务中,该事务使得对该数据库的更改一直存在,直到该方法完成,在这种情况下结果不会被刷新。
答案 1 :(得分:0)
根据我的经验,他们仍然不一定会在数据库中显示,直到他们最终都承诺。我正在使用Oracle,并且我能够让它们分批提交(在数据库中如此可见)的唯一方法是为每个批处理创建单独的事务并在刷新后将其关闭。但是,这导致最后冲洗过程结束时出现错误。我没有时间弄明白,使用上面的过程,无论数据负载有多大,我都不会遇到问题。
使用此方法仍然有很大帮助 - 它确实会刷新并清除会话。你可以看一下你的内存利用率。
就更新带有记录的表而言,表上是否有索引?有时索引会减慢大量插入/更新,因为数据库正试图保持索引新鲜。也许在导入/更新之前禁用索引,然后在完成后启用它?