백엔드/JPA

Batch Insert

infitry 2022. 7. 2. 06:52
반응형

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를 넣으면 된다.

반응형