Batch Insert
Batch Insert란?
# insert
INSERST INTO TABLE_A(name, phone)
VALUES ('test1', '01000000001')
# batch insert
INSERST INTO TABLE_A(name, phone)
VALUES ('test1', '01000000001'),
VALUES ('test2', '01000000001'),
VALUES ('test3', '01000000001'),
VALUES ('test4', '01000000001'),
VALUES ('test5', '01000000001')
만약 10,000 건의 insert가 필요한 경우, 1건 씩 DB에 요청을 하게되면 10,000 건의 커넥션을 맺게 된다.
서버에서 DB서버로 요청과 응답을 10,000번 하게 된다는 것
하지만 Batch Insert를 사용하면 1번의 커넥션으로 10,000 건의 Insert 요청을 할 수 있어 성능이 개선된다.
JPA에서의 Batch Insert
JPA에서는 Batch Insert를 지원하지만,
ID Generated Strateg를 IDENTITY로 지정하면 saveAll 메소드로 batch insert를 사용할 수 없다.
@GeneratedValue(strategy = GenerationType.IDENTITY)
이유는 실제 DB에 Insert를 해야 그 값을 얻을 수 있는데 영속성 컨텍스트에 저장하려면 ID 값을 알아야 한다.
방법을 찾다가 JPA JdbcTemplate를 이용하는 방법을 찾았다.
JdbcTemplate
JdbcTemplate은 spring-boot-starter-data-jpa 안에 포함되어있어
기존에 JPA를 사용하고 있다면, 별도의 설정이나 의존성 추가 없이 사용가능하다.
* mysql jdbc의 경우 jdbc url에rewriteBatchedStatements=true 옵션을 추가
해당 옵션을 추가하지 않으면 batch insert가 실행되지 않는다.
실제로 처리되는 쿼리를 확인하기 위해 profileSQL=true&logger=Slf4JLogger 추가한다.
String sql = "INSERT INTO TABLE_A "
+ "(name, phone) VALUES (?, ?)";
jdbcTemplate.batchUpdate(sql, new BatchPreparedStatementSetter() {
@Override
public void setValues(PreparedStatement ps, int i) throws SQLException {
TableA tableA = TableAList.get(i);
ps.setString(1, tableA.getName());
ps.setString(2, tableA.getPhone);
}
@Override
public int getBatchSize() {
return TableAList.size();
}
});
setValues는 values('', '')에 들어가는 값들을 세팅하는 메소드 이고
getBatchSize()는 batch insert의 size를 넣으면 된다.