我正在处理一个较大的csv文件,并且发现了有关批处理导入的文章http://naleid.com/blog/2009/10/01/batch-import-performance-with-grails-and-mysql/。我试图做同样的事情,但是似乎没有效果。

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

然后我还注意到,第一次将空白导入到空白表时,导入工作很快,但是当表已满并且实体应该更新或另存为新表时,整个过程非常缓慢。这主要是由于未清除内存,内存减少到1MB或更小,导致应用卡住了。那是因为不刷新 session 吗?

我的导入代码在这里:

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()
}

非常感谢您的帮助!

问候,

洛扎

P.S .:我的JVM内存总共有252.81 MB,但这是我和其他3个人的唯一测试环境。

最佳答案

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

使用此方法仍然有很大帮助-它确实刷新并清除了 session 。您可以查看您的内存利用率以查看该信息。

至于用记录更新表,您在表上有索引吗?有时索引会减慢这种大规模插入/更新的速度,因为数据库正在尝试使索引保持最新状态。也许在导入/更新之前禁用索引,然后在完成时启用索引?

08-28 22:54