Search
Duplicate

[Java] Save와 SaveAll 테스트 및 성능 테스트

순서
1
날짜
2023/01/15
사람
상태
Done
오늘은 JPA를 공부하다가. save 와 saveAll의 성능에대해 궁금하게 되었다.
두개다 테스트 코드를 작성해보고, 걸리는 시간을 기반으로 측정하였다.
결론적으로 이야기 하자면 saveAll이 save보다 최대 1.25배 ~ 2배정도 차이가 났다.
이유는 아래의 테스트 코드와 설명을 통해 전달하도록 하겠다.

1. Save

@Test @DisplayName("회원save 테스트") public void 회원save톄스트() { int memberCount = 10000; long beforeTime = System.currentTimeMillis(); for (int i = 0; i < memberCount; i++) { Member member = Member.createMember("typark"+i, 40); memberService.join(member); } long afterTime = System.currentTimeMillis(); long secDiffTime = (afterTime - beforeTime); //두 시간에 차 계산 System.out.println("시간차이(m) : "+secDiffTime); // 1026 }
Java
복사
1.
회원의 카운트를 10,000으로 작성.
2.
회원 저장함수 시작 전 시스템 시간을 적시
3.
10,000개의 회원을 저장
4.
저장 후 시스템 시간을 적시
5.
저장 후 시스템 시간 - 저장 전 시스템 시간을 = 총 걸린시간

2.saveAll

@Test @DisplayName("회원saveAll 테스트") public void 회원saveAll테스트() { int memberCount = 10000; List<Member> members = new ArrayList<>(); long beforeTime = System.currentTimeMillis(); for (int i = 0; i < memberCount; i++) { Member member = Member.createMember("typark"+i, 40); members.add(member); } memberService.joinAll(members); long afterTime = System.currentTimeMillis(); long secDiffTime = (afterTime - beforeTime); //두 시간에 차 계산 System.out.println("시간차이(m) : "+secDiffTime); // 750 }
Java
복사
1.
회원의 카운트를 10,000으로 작성.
2.
회원 저장함수 시작 전 시스템 시간을 적시
3.
10,000개의 회원을 리스트에 저장
4.
saveAll 함수에 리스트 저장
5.
저장 후 시스템 시간을 적시
6.
저장 후 시스템 시간 - 저장 전 시스템 시간을 = 총 걸린시간

결과

결과를 보면 save 보다 saveAll이 훨씬 빠르다는 것을 알 수 있다. 왜이런 현상이 발생되었는가?
1.
save 내부 함수
@Transactional @Override public <S extends T> S save(S entity) { Assert.notNull(entity, "Entity must not be null."); if (entityInformation.isNew(entity)) { em.persist(entity); return entity; } else { return em.merge(entity); } }
Java
복사
save 함수는 내부적으로 @Transactional 로 감싸저 있으며, 이는 스프링의 프록시 기반으로 동작이 된다. 즉) 호출이 될 때 프록시 기반의 객체를 가로채서 사용하는 객체의 함수가 작동되는 것이다.
2.
saveAll 내부 함수
@Transactional @Override public <S extends T> List<S> saveAll(Iterable<S> entities) { Assert.notNull(entities, "Entities must not be null!"); List<S> result = new ArrayList<>(); for (S entity : entities) { result.add(save(entity)); } return result; }
Java
복사
saveAll 함수도 내부적으로 @Transactional로 감싸져 있지만, 내부의 함수 save를 호출하게 된다. 이렇게 되면 프록시 기반으로 save가 동작하지 않기 때문에, 불필요한 프로세스가 없어지게되고, save를 호출하는 것보다 효율적으로 변경 되는 것이다.
오늘은 save와 saveAll의 차이점에 대해 설명하게 되었고, 다량의 데이터를 저장할 때는 saveAll을 활용해 좀 더 효율적으로 접근해야 되겠다.
참조 :