24

insert()MySQLデータベースに50万レコードを挿入するためにJDBCバッチを使用しようとしているメソッドを作成しました。

public void insert(int nameListId, String[] names) {
    String sql = "INSERT INTO name_list_subscribers (name_list_id, name, date_added)" + 
        " VALUES (?, ?, NOW())";
    Connection conn = null;
    PreparedStatement ps = null;

    try {
        conn = getConnection();
        ps = conn.prepareStatement(sql);

        for (String s : names ) {
            ps.setInt(1, nameListId); 
            ps.setString(2, s);
            ps.addBatch();
        }

        ps.executeBatch();

    } catch (SQLException e) {
        throw new RuntimeException(e);
    } finally {
        closeDbResources(ps, null, conn);
    }
}

しかし、このメソッドを実行しようとすると、次のエラーが発生します。

java.lang.OutOfMemoryError: Java heap space
    com.mysql.jdbc.ServerPreparedStatement$BatchedBindValues.<init>(ServerPreparedStatement.java:72)
    com.mysql.jdbc.ServerPreparedStatement.addBatch(ServerPreparedStatement.java:330)
    org.apache.commons.dbcp.DelegatingPreparedStatement.addBatch(DelegatingPreparedStatement.java:171)

に置き換えps.addBatch()ps.executeUpdate()削除するとps.executeBatch()、少し時間がかかりますが、問題なく動作します。この状況でバッチを使用することが適切かどうかを知っているかどうかを教えてください。適切である場合、なぜそれが得られるのOurOfMemoryErrorですか?

ありがとう

4

2 に答える 2

48

addBatchexecuteBatchバッチ挿入を実行するメカニズムを提供しますが、それでもバッチアルゴリズムを自分で実行する必要があります。

実行しているように、すべてのステートメントを同じバッチに単純に積み上げると、メモリが不足します。nレコードごとにバッチを実行/クリアする必要があります。の価値はnあなた次第です。JDBCはあなたに代わってその決定を下すことはできません。バッチサイズが大きいほど、処理は速くなりますが、大きすぎると、メモリが不足し、処理が遅くなったり失敗したりします。それはあなたが持っているメモリの量に依存します。

たとえば、バッチサイズを1000から始めて、そこからさまざまな値を試してみてください。

final int batchSize = 1000;
int count = 0;
for(String s : names ) {
   ps.setInt(1, nameListId); 
   ps.setString(2, s);
   ps.addBatch();

   if (++count % batchSize == 0) {
      ps.executeBatch();
      ps.clearBatch(); //not sure if this is necessary
   }
}
ps.executeBatch();   // flush the last few records.
于 2010-02-09T08:34:51.873 に答える
6

すべてのトランザクションをメモリに保持し、を呼び出したときにのみデータベースに送信するため、メモリが不足していますexecuteBatch

アトミックである必要がなく、パフォーマンスを向上させたい場合は、カウンターを保持して、n個のレコードexecuteBatchごとに呼び出すことができます。

于 2010-02-09T08:18:00.113 に答える