관리 메뉴

ballqs 님의 블로그

[Spring] JPA Save() vs SaveAll() vs Bulk Insert 본문

코딩 공부/Spring

[Spring] JPA Save() vs SaveAll() vs Bulk Insert

ballqs 2024. 8. 26. 19:04

DB에 데이터를 저장해야하는 일이 있을때 대용량으로 데이터를 넣어야하는 경우가 있다면 JPA에서는 매번 하나하나 Insert문을 만들어서 실행시키고 있을 것이다. 이건 대용량으로 insert 하는것에 매우 적합하지 않은 방법이다.

SQL에서는 insert 에 values 를 연달아 쓰는 방법이 바로 Bulk Insert 방법이다.

그렇게 글 내용대로 3가지를 비교해보도록 하겠다. 참조글 : Spring JPA Save() vs SaveAll() vs Bulk Insert


Save()

@Test
@Transactional
@Rollback
@DisplayName("Save() 테스트")
void Test1() {
    long startTime = System.currentTimeMillis();

    for (int i =1; i< 100000; i++){
        Schedule schedule = new Schedule();
        schedule.setTitle("title title title"+i);
        schedule.setContent("content content content"+i+1);
        schedule.setWeather("");
        User user = new User();
        user.setId(1L);
        schedule.setUser(user);
        scheduleRepository.save(schedule);
    }
    System.out.println("taken time = "+(System.currentTimeMillis() - startTime)+"ms");
}

 

save() 메서드를 사용했을때는 26243ms 즉 26s 243ms인 26초 가량이 걸렸습니다.

save() 메서드의 특징은 프록시 기반 동작을 하기 때문에 매번 save()가 호출될 떄 불필요한 프록시 과정이 발생할 수 있다.


SaveAll()

@Test
@Transactional
@Rollback
@DisplayName("SaveAll() 테스트")
void Test1() {
    long startTime = System.currentTimeMillis();

    List<Schedule> scheduleList = new ArrayList<>();
    for (int i =1; i< 100000; i++){
        Schedule schedule = new Schedule();
        schedule.setTitle("title title title"+i);
        schedule.setContent("content content content"+i+1);
        schedule.setWeather("");
        User user = new User();
        user.setId(1L);  // 예시로 user_id를 1로 설정
        schedule.setUser(user);  // Schedule에 User 설정
        scheduleList.add(schedule);
    }
    scheduleRepository.saveAll(scheduleList);
    System.out.println("taken time = "+(System.currentTimeMillis() - startTime)+"ms");
}

 

savaAll()를 사용했을땐 그리 많이 줄진 않았으나 24598ms 즉 24s 598ms.... 24초 정도가 걸렸다. save() 메서드 사용했을때보다 아주 살짝 빨랐다. 뭔 차이인가 싶긴하다... ㅠㅠ

다만 참조글에 인해서는 saveAll이 빠르다고는 하다....

saveAll() save()와 다르게 한 번의 트랜잭션을 생성하고, save()를 여러 번 호출하여 같은 인스턴스에서 내부 호출을 하기 때문에 프록시 로직을 타지 않게 되서 빠르다고 한다.


Bulk Insert

Insert에는 단건 삽입이 있고 Bulk 삽입이 있다.

단건 삽입

insert into member (name , email ) values ("이름" , "이메일")

 

Bulk 삽입

insert into member (name , email ) 
values 
	("이름" , "이메일"),
	("이름" , "이메일"),
	("이름" , "이메일");

 

하나씩 insert 하는것과 한번에 insert 하는 차이가 존재한다.

save() 와 saveAll() 는 단건 삽입에 해당한다.

 

코드

@Autowired
private JdbcTemplate jdbcTemplate;

@Test
@Transactional
@Rollback
@DisplayName("Bulk Insert 테스트")
void Test1() {

    long startTime = System.currentTimeMillis();

    List<Manager> managerList = new ArrayList<>();

    for (int i =1; i< 100000; i++){
        Manager manager = new Manager();
        manager.setManagerNm("이름");
        manager.setEmail("이메일");

        managerList.add(manager);
    }

    String sql = "INSERT INTO manager (manager_nm, email)"+
            "VALUES (?, ?)";

    jdbcTemplate.batchUpdate(sql,
            managerList,
            managerList.size(),
            (PreparedStatement ps, Manager manager) -> {
                ps.setString(1, manager.getManagerNm());
                ps.setString(2, manager.getEmail());
            });

    System.out.println("taken time = "+(System.currentTimeMillis() - startTime)+"ms");
}

 

8786ms 가 걸렸다. 앞에 했던 save() 와 saveAll()에 비해 지나치게 많이 줄은것이 확인이 된다.

앞으로는 대규모 데이터를 삽입해야할 일이 생기면 bulk insert를 사용해야겠다.