728x90
반응형
두 방식의 가장 큰 차이는 영속성 컨텍스트 사용 유무(메모리)와 동작 방식.
Spring Data JPA에서 saveAll(Iterable<T>)은 내부적으로 하나하나 save()를 호출하는 구조.
for문 돌면서 persist(insert) 또는 merge(update)를 반복.
??? : saveAll 안쓰고 네이티브 쿼리 써도 @Transactional 을 쓰기 때문에 jdbc 버퍼에 저장되니까 메모리 쓰는건 똑같지않아?
List<MyEntity> list = createMillionEntities(); // 100만 개 생성
myRepository.saveAll(list);
saveAll()은 단순히 SQL만 실행하는 게 아니라 다음을 함
1. 엔티티 객체 생성
2. 모두 영속성 컨텍스트에 등록
3. 변경 여부 추적(더티 체킹)
flush 시점까지 메모리 안에 유지
MyEntity 100만 개가 영속성 컨텍스트(cache)에 남아 있어서 메모리 폭발 위험 있음(OutOfMemory).
또한!!
saveAll(Iterable<S> entities) 메서드는 내부적으로 각 엔티티가 새로 추가되는 것인지, 기존 데이터의 업데이트인지 판단하기위해 Hibernate는 각 엔티티의 상태를 확인하기 위한 SELECT 를 실행한다.
-> select 100만번, insert(update) 100만번이란 소리
네이티브 쿼리는?
EntityManager.createNativeQuery("INSERT INTO ...").executeUpdate()
단순히 SQL 문자열만!! JDBC 버퍼에 넣는 것뿐이고
Java 객체를 영속성 컨텍스트에 넣지도 않고, 상태 추적도 없음
insert SQL 한 줄만 있으면 끝나니까 메모리 훨씬 적게 사용
수천 건 이상이면 네이티브 쿼리 추천
728x90
반응형
'SpringBoot' 카테고리의 다른 글
JPA 영속성 컨텍스트, Dirty Checking, 쓰기 지연, Spring Data JPA, Hibernate, JDBC (0) | 2025.04.03 |
---|---|
@GroovyASTTransformation 컴파일타임 조작, 어노테이션 동적 적용 (0) | 2025.02.24 |
호출 순서 TestBootstrapInitializer, TestExecutionListener, setupSpec, ApplicationContextInitializer (0) | 2025.01.10 |
삽질. groovy, spock 통합테스트 적용 (0) | 2024.12.19 |
spock @LocalServerPort 할당 시점, setup, setupSpec 차이 (0) | 2024.11.20 |
댓글