728x90
반응형
SMALL
문제상황
기존에 대량의 데이터를 데이터베이스에 저장할 때, JPA의 saveAll 기능을 사용하고 있었습니다. 하지만 많은 양의 데이터를 처리할 때 성능 이슈가 발생하여, 보다 효율적인 방법이 필요했습니다. 특히, 한 번에 수천 건의 데이터를 삽입하는 경우, JPA의 saveAll은 예상보다 느린 성능을 보였습니다. 이를 해결하기 위해 JDBC 기반의 batchInsert 방식으로 코드를 개선했습니다.
수정코드
public List<SmsSendTargetDto> bulkInsertSmsMsgSendDetail(SmsQueueDto smsQueueDto, String msgGroupId) {
String sql = "INSERT INTO table (msg_id, msg_group_id, recv_no, user_seq, send_state_cd, daou_msg_id, app_uid, reg_user_id, reg_datetime) VALUES (?,?,?,?,?,?,?,?,?)";
List<SmsSendTargetDto> sendTargetDtoList = new ArrayList<>();
jdbcTemplate.batchUpdate(sql, new BatchPreparedStatementSetter() {
@Override
public void setValues(PreparedStatement ps, int i) throws SQLException {
String msgId = UUID.randomUUID().toString();
MsgSendMasterDto dto = smsQueueDto.getMsgSendMasterDto();
SmsDetailDto smsDetailDtos = smsQueueDto.getSmsDetailDtos().get(i);
ps.setString(1, msgId);
ps.setString(2, msgGroupId);
try {
ps.setString(3, AES256Cipher.encrypt(smsDetailDtos.getRecvNo()));
} catch (Exception e) {
throw new RuntimeException(e);
}
if (smsDetailDtos.getUserSeq() != null) {
ps.setLong(4, Long.parseLong(smsDetailDtos.getUserSeq()));
} else {
ps.setNull(4, Types.BIGINT); // BIGINT 타입의 NULL 처리
}
ps.setString(5, "READY");
ps.setString(6, null);
ps.setString(7, null);
ps.setString(8, dto.getRegUserId());
ps.setTimestamp(9, Timestamp.valueOf(now()));
sendTargetDtoList.add(SmsSendTargetDto.builder()
.msgId(msgId)
.recvNo(smsDetailDtos.getRecvNo())
.build());
}
@Override
public int getBatchSize() {
return smsQueueDto.getSmsDetailDtos().size();
}
});
return sendTargetDtoList;
}
개선된 부분
- 성능 향상: 기존의 JPA saveAll 방식을 JDBC의 batchInsert로 전환함으로써, 대량의 데이터를 훨씬 빠르게 삽입할 수 있었습니다. 이 방법은 특히 트랜잭션을 관리하고 성능을 높이는 데 효과적입니다.
- null 처리: user_seq 필드가 null일 수 있는 상황을 고려하여, null 값일 경우 setNull(4, Types.BIGINT)을 사용해 데이터베이스에 null로 저장하도록 처리했습니다.
- 에러 처리: AES256Cipher.encrypt 과정에서 발생할 수 있는 예외를 처리하여 안정성을 높였습니다.
결론
대량의 데이터를 삽입할 때 JPA의 saveAll을 사용하는 것보다 JDBC의 batchInsert를 사용하는 것이 성능 측면에서 훨씬 효율적입니다. 특히, null 값 처리와 예외 상황에 대한 고려를 통해 안정성을 확보할 수 있었습니다. 대규모 트랜잭션을 처리하는 경우에는 JDBC 기반의 배치 삽입을 적극 활용하는 것이 좋습니다.
728x90
반응형
LIST
'트러블슈팅' 카테고리의 다른 글
Redis를 이용한 예약 메세지 시스템 개선: RabbitMQ의 FIFO 한계를 극복한 방법 (2) | 2024.10.04 |
---|---|
WebClient를 이용한 백프레셔 적용하기 (2) | 2024.10.04 |