私は今バッチを使用しています:
String query = "INSERT INTO table (id, name, value) VALUES (?, ?, ?)";
PreparedStatement ps = connection.prepareStatement(query);
for (Record record : records) {
ps.setInt(1, record.id);
ps.setString(2, record.name);
ps.setInt(3, record.value);
ps.addBatch();
}
ps.executeBatch();
上記のコードが次のコードと同等かどうか疑問に思っています。そうでない場合、どちらが速いですか?
String query = "INSERT INTO table (id, name, value) VALUES ";
for (Record record : records) {
query += "(" + record.id + ",'" + record.name + "'," + record.value + "),";
}
query = query.substring(1, query.length() - 1);
PreparedStatement ps = connection.prepareStatement(query);
ps.executeUpdate();
まず、クエリ文字列の連結を使用すると、PreparedStatementメソッド固有の型変換が失われるだけでなく、データベースで実行される悪意のあるコードに対して脆弱になります。
2番目に、PreparedStatementsは以前にデータベース自体にキャッシュされていました。これにより、プレーンステートメントよりも優れたパフォーマンスの改善が既に得られています。
自動コミットがfalseに設定されている限り、executeBatch
はexecuteUpdate
よりもパフォーマンスが向上します。
connection.setAutoCommit(false);
PreparedStatement ps = connection.prepareStatement(query);
for (Record record : records) {
// etc.
ps.addBatch();
}
ps.executeBatch();
connection.commit();
挿入するアイテムの数が多い場合、深刻なパフォーマンスの問題に直面する可能性があります。したがって、バッチサイズを定義し、バッチサイズに達したときにクエリを常に実行する方が安全です。
次のサンプルコードのようなものが動作するはずです。このコードを効率的に使用する方法の詳細については、こちらをご覧ください link 。
private static void insertList2DB(List<String> list) {
final int batchSize = 1000; //Batch size is important.
Connection conn = getConnection();
PreparedStatement ps = null;
try {
String sql = "INSERT INTO theTable (aColumn) VALUES (?)";
ps = conn.prepareStatement(sql);
int insertCount=0;
for (String item : list) {
ps.setString(1, item);
ps.addBatch();
if (++insertCount % batchSize == 0) {
ps.executeBatch();
}
}
ps.executeBatch();
} catch (SQLException e) {
e.printStackTrace();
System.exit(1);
}
finally {
try {
ps.close();
conn.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public void insertBatch(final List<Record > records ) {
String query = "INSERT INTO table (id, name, value) VALUES (?, ?, ?)";
GenericDAO.getJdbcTemplate().batchUpdate(sql, new BatchPreparedStatementSetter() {
@Override
public void setValues(PreparedStatement ps, int i) throws SQLException {
Record record = records .get(i);
ps.setInt(1, record.id);
ps.setString(2, record.name);
ps.setInt(3, record.value);
}
@Override
public int getBatchSize() {
return records.size();
}
});
}