반응형
대량 삽입 (Bulk Insert)와 JPA의 한계
JPA는 객체 지향적 데이터 처리를 위해 설계되었기 때문에, 대량 삽입(Bulk Insert)와 같은 작업에 최적화되어 있지 않음
Bulk Insert 란?
아래와 같이 여러 insert 문을 하나의 쿼리에서 날릴 수 있는 방법
INSERT INTO 테이블 (컬럼1, 컬럼2, ...)
VALUES
(값1, 값2, ...),
(값11, 값22, ...),
하지만 JPA는 영속성 컨텍스트를 통해 데이터를 관리하므로, 이러한 형태의 Bulk Insert를 지원하지 않음
JPA의 Save vs SaveAll 성능 비교
save
: 하나의 엔티티를 저장할 때마다 별도의 쿼리를 실행saveAll
: 여러 엔티티를 한 번에 저장하도록 최적화되어 있지만, 여전히 엔티티별로 개별 INSERT 쿼리를 실행
JPA vs MyBatis Insert 200
MyBatis
: 200개의 데이터를 하나의 쿼리로 처리JPA
: 200개의 데이터를 저장하면 200개의 개별 INSERT 쿼리가 발생
Batch Insert 설정
JPA에서 hibernate.jdbc.batch_size 설정을 통해 Batch Insert를 활성화 가능
이 경우, JPA는 데이터를 일정 개수(batch size)만큼 묶어서 전송함, 하지만 묶음 단위로 여러 개의 INSERT 쿼리가 날아가는 것은 동일
spring.jpa.properties.hibernate.jdbc.batch_size=200
spring.jpa.properties.hibernate.order_inserts=true
Batch 설정을 통해 성능이 일부 개선될 수 있지만, MyBatis의 Bulk Insert 방식에 비해서는 여전히 느림
참고 블로그
https://datamoney.tistory.com/319
JPA와 MyBatis 업데이트 처리 비교
JPA의 업데이트 처리
JPA에서 엔티티를 저장할 때, 해당 엔티티의 Primary Key(PK)가 테이블에 존재하는지 여부에 따라 아래와 같이 처리됨
- PK가 존재하면: UPDATE
- PK가 없으면: INSERT 즉, save 메서드는 insert-or-update 형태
repository.save(Entity.builder()
.id(1L) // 기존 PK
.name("수정된 이름")
.build());
MyBatis의 한계
MyBatis는 INSERT와 UPDATE를 명시적으로 구분해야 합니다.
즉, 동일한 작업을 위해 INSERT와 UPDATE 중 하나를 선택해야 하며, 두 작업을 한 번에 처리할 수 없습니다.
해결 방법: 데이터베이스 기능 활용
일부 데이터베이스(PostgreSQL 등)는 충돌이 발생한 경우 업데이트를 수행할 수 있는 기능을 제공하는데,
이러한 기능을 통해서만 insert-or-update 형태 구현가능
- PostgreSQL의 ON CONFLICT 예시
INSERT INTO table_name (id, name)
VALUES (#{id}, #{name})
ON CONFLICT (id) DO UPDATE
SET name = EXCLUDED.name;
- ON CONFLICT: 충돌이 발생했을 경우
- EXCLUDED: 새로 삽입하려던 값을 참조.
결론
- 대량 삽입: JPA는 Bulk Insert에 적합하지 않으며, MyBatis 또는 네이티브 SQL을 사용하는 것이 성능상 유리합니다.
- 업데이트 처리: JPA는 save 메서드를 통해 insert-or-update를 유연하게 처리하지만, MyBatis는 명시적으로 작업을 구분해야 합니다. PostgreSQL의 ON CONFLICT와 같은 데이터베이스 기능을 활용하면 이를 보완할 수 있습니다.
반응형
'Spring > SpringBoot (JPA)' 카테고리의 다른 글
[스프링부트] 개발서버 운영서버 하나의 설정파일로 실행하기(application.yml) (1) | 2024.11.22 |
---|---|
[JPA] Postgreql 타임스탬프 매핑, 생성 수정시간 자동생성 (1) | 2024.08.27 |