1

我正在处理一个大型 csv 文件,我发现这篇关于批量导入的文章:http: //naleid.com/blog/2009/10/01/batch-import-performance-with-grails-and-mysql/。我尝试做同样的事情,但似乎没有任何效果。

每次刷新后是否应该在数据库中查看实例?因为当我尝试查询“SELECT COUNT(*) FROM TABLE1”时,现在有 0 个或所有实体,所以看起来这些实例是一次性提交的。

然后我还注意到第一次导入空白表时导入工作很快,但是当表已满并且实体应该更新或另存为新时,整个过程非常缓慢。这主要是因为内存没有被清理并减少到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()
}

非常感谢您的帮助!

问候,

洛伊扎

PS:我的 JVM 内存总共有 252.81 MB,但它只是我和其他 3 人的测试环境。

4

2 回答 2

6

我曾经遇到过类似的问题。然后我意识到原因是因为我是在 grails 服务中做的,默认情况下它是事务性的。因此,对服务中方法的每次调用本身都包装在一个事务中,该事务使对该数据库的更改一直存在,直到方法完成,在这种情况下,结果不会被刷新。

于 2012-11-13T10:05:51.580 回答
0

根据我的经验,在它们最终全部提交之前,它们仍然不一定在数据库中可见。我正在使用 Oracle,我能够让它们分批提交(在数据库中可见)的唯一方法是为每个批次创建单独的事务并在刷新后将其关闭。然而,这导致在最后一次刷新的过程结束时出现错误。我没有时间弄清楚,并且使用上面的过程,无论数据负载有多大,我都不会遇到问题。

使用这种方法仍然有很大帮助——它确实会刷新和清除会话。您可以查看您的内存使用情况以了解这一点。

至于用记录更新表,表上有索引吗?有时索引会减慢像这样的大量插入/更新,因为数据库试图保持索引新鲜。也许在导入/更新之前禁用索引,然后在完成时启用?

于 2012-05-11T22:47:02.627 回答