2012-04-16 19 views
-1

私は約25,000行のExcelシートを持っています。 Excelシートの各行は私のテーブルの行にもなります。私は次のことをやろうとしました。私はbatchSizeを25から50,100,500に変更しようとしました。いずれも動作しません。誰かが私に間違っていることを教えてもらえますか? JVMのヒープサイズを変更することは私の選択肢ではありません。クラスjava.lang.OutOfMemoryError Oracleデータベースにデータを保存中

public void saveForecast(List list) throws FinderException{ 
    final Session session = getCurrentSession(); 
    final int batchSize = 25; 
    Connection con = null; 
    PreparedStatement pstmt = null; 
    Iterator iterator = list.iterator(); 
    int rowCount = list.size(); 
    String sqlStatement = "INSERT INTO DMD_VOL_UPLOAD (ORIGIN, DESTINATION, DAY_OF_WEEK, EFFECTIVE_DATE, DISCONTINUE_DATE, VOLUME)"; 
    sqlStatement += " VALUES(?, ?, ?, ?, ?, ?)"; 
    System.out.println(sqlStatement); 
    System.out.println("Number of rows to be inserted: "+ rowCount); 
    System.out.println("Starting time: "+new Date().toString()); 
    try{ 
     con = session.connection(); 
     for(int i=0; i<rowCount; i++){ 
      ForecastBatch forecastBatch = (ForecastBatch) iterator.next();    
      pstmt = con.prepareStatement(sqlStatement);    
      pstmt.setString(1, forecastBatch.getOrigin()); 
      pstmt.setString(2, forecastBatch.getDestination()); 
      pstmt.setInt(3, forecastBatch.getDayOfWeek()); 

      java.util.Date effJavaDate = forecastBatch.getEffectiveDate(); 
      java.sql.Date effSqlDate = new java.sql.Date(effJavaDate.getTime());     
      pstmt.setDate(4, effSqlDate);    
      java.util.Date disJavaDate=forecastBatch.getDiscontinueDate(); 
      java.sql.Date disSqlDate = new java.sql.Date(disJavaDate.getTime()); 

      pstmt.setDate(5, disSqlDate);    
      pstmt.setInt(6, forecastBatch.getVolumeSum()); 

      pstmt.addBatch(); 
      if(i % batchSize == 0){ 
       pstmt.executeBatch(); 
       session.flush(); 
       session.clear(); 
      } 
     } 
     pstmt.executeBatch(); 
     pstmt.close(); 
     System.out.println("Ending Time: "+ new Date().toString()); 
    }catch(SQLException e){ 
     e.printStackTrace(); 
     throw new FinderException(e); 
    } 
    finally{ 
     HibernateUtil.closeSession(); 
    } 
} 

}

+0

私は1)forループとイテレータを使用してリストをトラバースしています。 r(イテレータに投票します)。また、より小さなExcelファイルではどうなりますか?どのような時点でそれが詰まるのですか? –

+0

ヒープダンプを生成し、メモリプロファイラを使用します。問題の原因を推測する必要はありません。 – jtahlborn

+0

スプレッドシートのディスク上のサイズは?あなたはどのリーダーの実装を使用していますか? – nsfyn55

答えて

1

ループ内に新しいステートメントを作成していますが、ループの終了後に最後のステートメントを閉じるだけです。つまり、実際には25000個のステートメントを作成し、1個だけをクローズして24999個のステートメントをオープンしていることになります。これは、リソースが不足していることに驚くことではありません。

さらに、バッチステートメントを正しく使用していない場合は、ステートメントを一度作成してからパラメータを設定し、addBatchを呼び出し、さらにパラメータを設定し、addBatchをもう一度呼び出すなどしてからexecuteBatchを呼び出します。あなたはバッチですべての値を提出したい

EDIT:。

あなたはおそらくforループと私はセッションフラッシュ/クリアはいずれかが必要です呼び出すとは思わない前のprepareStatementコールを移動することによって、これを修正します。

+0

forループの外側にprepareStatementを移動し、今朝実行したときに機能しました。それはすべての25,000行を挿入しました。私はそれが再びそれをすることができるかどうかを見たかった。しかし、もう2回25,000行を挿入しようとすると、システムがハングアップし、次のメッセージが表示されます。 "スレッド" WebContainer:0 "(0000001e)が734917ミリ秒間アクティブであり、ハングアップしている可能性があります。 s)が停止している可能性があります。あまりにも多くのリソースを使用していますか?一度に25,000行しかありません。今では、100行のデータを挿入することさえできません。 – Susie

+0

私は他の問題が何かを理解しました。私はコミットしていませんでした。私はbatchSizeを1000に変更し、12秒で25,000行を節約できました。私はそれが十分だと思う。皆さんのお手伝いをありがとうございます。それを12秒より早くする方法があるかどうかを知ることはいいでしょうが。私はバッチサイズを5000に増やそうとしましたが、それは1秒遅くなりました。 – Susie

1

あなたの主な問題は、すべての単一の行の文を再準備しているということのようです。あなたは文を一度準備する必要があります。これにより、大量のメモリが消費される可能性があります。

+0

ありがとうございます。私はこの文をループの外側に置く。pstmt = con.prepareStatement(sqlStatement);それは問題のその部分を解決するようです。 15,000行まで、テーブルに挿入することができました。 Excelシートの行数を15,000から25,000に増やすと、クラッシュするだけです。基本的には何も起こりません。次の動くべきことは何ですか?私はバッチサイズを50に増やし、それがどのように動作するかを見てみよう。 – Susie

関連する問題