1

私は、いくつかの比較的小さなdbオブジェクトを1 dbから次のdbに移行するための、貧乏人のetlツールとしてgrailsを使用しています。あるデータベース(mysql)からデータを読み取り、別のデータベース(pgsql)に書き込むコントローラーがあります。それらは類似したドメインオブジェクトを使用しますが、grails 2.1.Xでのマルチデータソースサポートの制限により、まったく同じではありません。

以下に私のコントローラーとサービスコードが表示されます。

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

これの多くは私自身のコードから取得され、 http://naleid.com/blog/2009/10/01/batch-import-performance-with-grails-and-mysqlに見られるのと同様のパフォーマンスを得るために微調整されています//

したがって、私のコードを確認する際に、zipcode_pg.save()が呼び出されるたびに、挿入ステートメントが作成され、データベースに送信されます。dbの一貫性には適していますが、一括操作には適していません。

インスタントフラッシュの原因は何ですか(注:データソースとcongig groovyファイルに関連する変更はありません)?このレートでは、100の各バッチ(1秒あたり14の挿入)を処理するのに約7秒かかります。これは、10,000の行を処理する場合、非常に長い時間です...

提案に感謝します。

注:純粋なETLツールの使用を検討しましたが、ドメインとサービスロジックが既に構築されているため、grailsを使用するとリソースを適切に再利用できると考えられます。しかし、このような大量の操作の品質を想像していませんでした

4

1 に答える 1

1

ドメイン オブジェクトが表示されない場合、これは単なる予感ですが、save() 呼び出しで validate:false も指定してみてください。Validate() は、Grails にそうしないように指示しない限り、save() によって呼び出されます。たとえば、PGZipcode ドメイン オブジェクトの任意のフィールドに一意の制約がある場合、Hibernate は新しいレコードごとに挿入を実行して、DBMS の一意の機能を活用し、適切な検証を実行する必要があります。他の制約も DBMS クエリを必要とする場合がありますが、今は一意のジャンプだけを思い浮かべてください。

Grails Persistenceから: トランザクションのライトビハインド

Hibernate は可能な限りデータベースの更新をキャッシュし、フラッシュが必要であることがわかっている場合、またはフラッシュがプログラムによってトリガーされた場合にのみ、実際に変更をプッシュします。Hibernate がキャッシュされた更新をフラッシュする一般的なケースの 1 つは、キャッシュされた情報がクエリ結果に含まれる可能性があるため、クエリを実行する場合です。ただし、競合しない保存、更新、および削除を行っている限り、セッションがフラッシュされるまでそれらはバッチ処理されます。


または、Hibernate セッションのフラッシュ モードを明示的に設定してみてください。

sessionFactory.currentSession.setFlushMode(FlushMode.MANUAL);

デフォルトのフラッシュモードはAUTOかもしれないという印象を受けています。

于 2012-11-26T14:25:32.590 に答える