0

これが私のコードです:

HibernateUtil.pushFlushMode(FlushMode.MANUAL);
getCurrSess().beginTransaction();
try {
    for(i=0; i<list.size(); i++) {
        Obj dummy = list.get(i);
        // Here Multiple things can happen like selects, save, update and deletes of different objects which are related to dummy object....
        if (i > 0 && (i % 10 == 0)) {
            getCurrSess().getTran().commit();
            getCurrSess().beginTransaction();
            if (i % BATCH_SIZE == 0) {
                getCurrSess().flush();
                Thread.sleep(20);
            }
        }
    } 
} catch(Exception e) {
    getCurrSess().getTran().rollback();
} finally {
    HibernateUtil.popFlushMode();
}

フラッシュは、コミットされた 10 個のトランザクション (i=100) ごとに発生します。これは、多くの処理を必要とするバックグラウンド ジョブの一部です。オブジェクトの数は約 20,000 であり、遅延初期化例外が発生するため、プロセス全体が終了するまでセッションをクリアできません。私のコードは正常に動作しますが、ここでは手動モードでのフラッシュとコミットのシーケンスに悩まされています。これをより良い方法で行うことはできますか?

4

2 に答える 2

0

10モジュロで定数を使用した理由は何ですか?

あなたは常に理由のために何かをしたいと思うべきです:-) 私はどういう意味ですか?

スループットを向上させたい場合、または RAM の量が少ない場合は、小さなトランザクションがこの機能をもたらすため、反復内のすべてのサイクルでキャッシュ フラッシュとクリアを提供します。

この要件がない場合は、最後にコミットするか、反復中にコミットするかは、リストのサイズによって異なります。10十分な場合もあれば、少ない場合もあれば、多すぎる場合もあるため、定数に注意してください。セッション内のオブジェクト数や占有メモリなど、他の重要な兆候に従っていつフラッシュするかを決定したいと思います。休止状態のキャッシュのサイズだけでなく、データベースのトランザクション ログも気にする必要があることに注意してください。

パフォーマンスを気にするなら、ステートレス セッションを見てください。私は何年も前にいくつかのパフォーマンステストを行いました (.NET)

于 2013-08-22T07:06:10.953 に答える
0

私は、この種の操作中に OptimisticLockExceptions が頻繁に発生するアプリケーションで作業し、それを修正するためにバッチを再実行しました。欠点は、たとえば、データベースがバッチの途中でオフラインになった場合、破損したデータベースを取得できることです。

HibernateUtil.pushFlushMode(FlushMode.MANUAL);
try {
  int batchIndex = 0;
  int numAttempts = 0;
  while (batchIndex < list.size()) {
    listEnd = batchIndex+BATCH_SIZE;
    if(listEnd > list.size()) {
      listEnd = list.size();
    }
    ArrayList<> sublist = new ArrayList<>(list.subList(batchIndex, batchIndex+BATCH_SIZE));
    getCurrSess().beginTransaction();
    try {
      for(Object obj : list) {
        //Here multiple things can happen like selects, save, update, and deletes
      }
      getCurrSess().flush();
      getCurrSess().commit();
      batchIndex += BATCH_SIZE;
    } catch (Exception e) {
      getCurrSess().getTran().rollback();
      numAttempts++;
      if(numAttempts == MAX_ATTEMPTS) {
        throw new RuntimeException("Exceeded maximum number of attempts for batch operation, database is corrupted.");
      }
    }
  }
} finally {
  HibernateUtil.popFlushMode();
}

データベースの破損を絶対に許容できない場合は、単一のトランザクションを使用する必要があります。

HibernateUtil.pushFlushMode(FlushMode.MANUAL);
try {
    getCurrSess().beginTransaction();
    try {
      for(int i = 0; i < list.size(); i++) {
        Object obj = list.get(i);
        //Here multiple things can happen like selects, save, update, and deletes
        if(i % BATCH_SIZE == 0) {
          getCurrSess().flush();
        }
      }
      getCurrSess().commit();
    } catch (Exception e) {
      throw new RuntimeException("Error occurred during batch.  Batch aborted.");
    }
  }
} finally {
  HibernateUtil.popFlushMode();
}

しかし、20,000 個のオブジェクトがある場合、明らかにこれでは優れたパフォーマンスが得られません (実際、最初のアプローチでさえ優れたパフォーマンスにはなりません)。20,000 個のオブジェクトがある場合、パフォーマンスを改善できる唯一の方法は、バッチごとにフラッシュしてクリアすることです。これは、遅延イニシャライザ例外を回避するために、操作方法を綿密に管理する必要があることを意味します。

于 2013-08-21T21:10:47.050 に答える