我将grails用作可怜的etl工具,用于将一些相对较小的db对象从1db迁移到下一个。我有一个 Controller ,它从一个数据库(mysql)读取数据并将其写入另一个数据库(pgsql)。它们使用相似的域对象,但由于grails 2.1.X中对多数据源支持的限制,它们并不完全相同。

在下面,您将看到我的 Controller 和服务代码:

class GeoETLController {

    def zipcodeService

      def migrateZipCode() {
        def zc = zipcodeService.readMysql();
        zipcodeService.writePgSql(zc);

        render{["success":true] as JSON}
    }
}

和服务:
class ZipcodeService {

    def sessionFactory
    def propertyInstanceMap = org.codehaus.groovy.grails.plugins.DomainClassGrailsPlugin.PROPERTY_INSTANCE_MAP

    def readMysql() {
        def zipcode_mysql = Zipcode.list();
        println("read, " + zipcode_mysql.size());
        return zipcode_mysql;
    }

    def writePgSql(zipcodes) {

        List<PGZipcode> zips = new ArrayList<PGZipcode>();
        println("attempting to save, " + zipcodes.size());
        def cntr = 0;
        zipcodes.each({ Zipcode zipcode ->
            cntr++;

            def props = zipcode.properties;
            PGZipcode zipcode_pg = new PGZipcode(zipcode.properties);

            if (!zipcode_pg.save(flush:false)) {
                zipcode_pg.errors.each {
                    println it
                }
            }
            zips.add(zipcode_pg)
            if (zips.size() % 100 == 0) {
                println("gorm begin" + new Date());
                // clear session here.
                this.cleanUpGorm();
                println("gorm complete" + new Date());

            }

        });
        //Save remaining
        this.cleanUpGorm();
        println("Final ." + new Date());
    }

    def cleanUpGorm() {
        def session = sessionFactory.currentSession
        session.flush()
        session.clear()
        propertyInstanceMap.get().clear()
    }
}

其中大部分来自我自己的代码,然后进行调整以尝试获得与oj​​it_a类似的性能

因此,在检查我的代码时,每当调用zipcode_pg.save()时,都会创建一个插入语句并将其发送到数据库。对数据库一致性有利,对批量操作不利。

我立即进行刷新的原因是什么(请注意:我的数据源和congig groovy文件没有相关更改)?以这种速度,每100批处理(每秒14次插入)大约需要7秒,而当您处理10,000行时,这是很长的时间...

欣赏建议。

注意:我考虑使用纯ETL工具,但是由于已经构建了如此多的域和服务逻辑,因此使用grails可以很好地重用资源。但是,没有想到这种批量操作的质量

最佳答案

没有看到您的域对象,这只是一种预感,但是我也可以尝试在save()调用中指定validate:false。 Validate()由save()调用,除非您告诉Grails不要这样做。例如,如果您对PGZipcode域对象中的任何字段都具有唯一约束,则Hibernate必须在每个新记录上进行插入,以利用DBMS的唯一功能并执行适当的验证。其他约束条件也可能需要DBMS查询,但现在只有唯一的想法要注意。

Grails Persistence: Transaction Write-Behind



或者,您可以尝试显式设置Hibernate session 的flush mode:

sessionFactory.currentSession.setFlushMode(FlushMode.MANUAL);

我印象中默认的冲洗模式可能是AUTO。

关于postgresql - Grails保存不尊重刷新选项,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/13555067/

10-12 12:45
查看更多