postgresql - Grails 保存不尊重刷新选项

标签 postgresql grails grails-orm

我正在使用 grails 作为穷人的 etl 工具,用于将一些相对较小的数据库对象从 1 db 迁移到下一个 db。我有一个 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()
    }
}

其中大部分内容取 self 自己的代码,然后进行调整以尝试获得与 http://naleid.com/blog/2009/10/01/batch-import-performance-with-grails-and-mysql/ 中所见相似的性能

因此,在检查我的代码时,每当调用 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 caches database updates where possible, only actually pushing the changes when it knows that a flush is required, or when a flush is triggered programmatically. One common case where Hibernate will flush cached updates is when performing queries since the cached information might be included in the query results. But as long as you're doing non-conflicting saves, updates, and deletes, they'll be batched until the session is flushed.


或者,您可以尝试设置 Hibernate session 的 flush mode明确地:

sessionFactory.currentSession.setFlushMode(FlushMode.MANUAL);

我的印象是默认的刷新模式可能是 AUTO。

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

相关文章:

grails - 查看多对一表时使用 Criteria 正确分页 (Grails)

grails - 为什么没有为使用 Grails 3.2 的单元测试注入(inject) sessionFactory?

python - django.db.utils.ProgrammingError : relation already exists

ajax - 将表单发布到具有异步结果的另一页

grails - Grails-显示正确的类(class)名称

hibernate - 发生异常后如何从 `don' 恢复 t 刷新 session `错误?

java - 映射遗留模型 - 仅具有唯一约束的表可以用作域类?

postgresql - 如何从 IBM WSJdbc41Connection 解包 PostgreSQL 连接

postgresql - Docker 没有获取 Postgres 环境变量

postgresql -/var/lib/postgres/data 存在但不为空