ハイベルナーの大容量データ操作


  • 一括追加
  •  
    実際の開発において、私たちは百万件以上のデータに遭遇しましたか?例えば、一度に10万件のデータを保存するには、私達の正常な考え方によって、こう書くべきです。
     
    session.beginTransaction();
    for(int i = 0,i<=100000,i++){
          TUser user = new TUser();
          session.save("user No:"+i);
    }
    session.getTransaction().commit();
     
     でもこれで何か問題がありますか?プログラムは必ずOutOfMemoryErrer異常で終了します。どうしてですか?なぜなら、ヒベルナはsession.save()を呼び出すたびに、このオブジェクトを自身の内部キャッシュに入れて管理しています。内部キャッシュ(1級キャッシュ)は2級キャッシュと違って、2級キャッシュはその中の最大容量を指定することができますが、内部キャッシュはこのような制限がありません。
    一度に1百万のデータを入れて、循環に従って、メモリは消耗されて、OutOfMemoryErrの異常を生みました。
     
    このような問題はどう解決しますか?
     
  • まず普通のJDBCでどう解決しますか?
  •  
     
    String sql = "insert into TUser(name) values(?)";
    PreparedStatement ps = conn.prepareStatement(sql);
    
    for(int i=0,i<1000000,i++){
        ps.setString(1,"user "+i);
        ps.addBatch();
    }
    
    int[] counts = ps.executeBatch();
     
     ここでのps.addBatch()方法は、SQLの数の操作ロットを取得性能の向上に提出する。
     
  • ヒベルナにおける解決:
  • session.beginTransaction();
    for(int i=0,i<1000000,i++){
       TUser user = new TUser();
       user.setName("user:"+i);    
       session.save(user);
       if(i%25 == 0){
          session.flush();
          session.clear();
       }
    }
    session.getTransaction().commit();
     
     段階的な呼び出しsession.cllear()このようにすれば、内部キャッシュ(一級キャッシュ)が占有する空間を合理的な範囲内に維持することができる。
    しかし、このように導入するにはかなり時間がかかります。しかし、まだ判断しなければならないです。この時、ヒップホップはより良い解決策を提供してくれました。
     
    <property name="hibernate.jdbc.batch_size">25</property>
     このように、SQLをHibenrateに毎回提出する数量を設定しました。