- MySQL 을 사용 중인 환경에서 Hibernate의 각 GenerationType이 PK를 생성하는 방식을 이해한다.
GenerationType#
GenerationType
: JPA에서 PK를 생성하는 전략을 나타내는 enumTABLE
: 데이터베이스 테이블을 사용해서 PK 할당SEQUENCE
: 데이터베이스 시퀀스를 사용해서 PK 할당IDENTITY
: 데이터베이스의 식별자 컬럼(MySQL의 AUTO_INCREMENT)을 사용해서 PK 할당UUID
: 애플리케이션에서 UUID를 생성해서 PK 할당- JPA 3.1, Hibernate 6.2부터 지원 시작
AUTO
: 사용 중인 데이터베이스 종류에 따라서 자동으로 전략 선택
GenerationType.AUTO의 전략 선택 과정#
Hibernate 5.2#
- Spring Boot 2부터
hibernate.id.new_generator_mappings
가 true
로 바뀌면서, MySQL 을 사용할 때 AUTO를 사용하면 UUID 타입의 경우를 제외하고는 TABLE 전략을 사용해서 PK를 생성하게 된다.

Hibernate 6.0부터#
- 6.0 부터는 동작이 단순화되었다.
- 아래와 같이 동작하면서 MySQL에서 AUTO 방식을 사용할 때는 IDENTITY로 동작하는 경우가 절대 없어졌다.

IDENTITY 전략의 특징#
- IDENTITY 방식은 INSERT 쿼리를 먼저 실행해야 ID를 얻을 수 있기 때문에 쓰기 지연을 할 수가 없다.
- 또한 IDENTITY 방식은 batch insert를 할 수 없어 대량의 쓰기가 자주 발생한다면 성능에 영향을 줄 수 있다.
TABLE 전략의 특징#
allocationSize
만큼 테이블에서 id를 가져와서 메모리에 가져와서 DB 왕복을 줄인다.- id를 가져오고 업데이트하기 위한 쿼리는 원래 저장하려는 엔티티와 별도 트랜잭션으로 실행되어 동시성 성능이 떨어지는 것을 방지한다.
- 예를 들어 아래와 같은
Product
엔티티를 저장할 때 현재 메모리에 id 정보가 없다면 3개의 쿼리가 발생할 것이다.
IDENTITY vs TABLE#
- IDENTITY는 batch insert가 지원되지 않고, TABLE은 insert를 위해 추가적인 쿼리가 발생한다는 단점이 존재한다.
- 조사를 해보다가 Hibernate 개발자의 의견을 확인할 수 있었다.
실험해보기#
- hibernate 6.4.1을 기준으로 여러 개의 엔티티를 추가할 때의 성능을 비교해본다.
Player
: TABLE 전략 사용. allocationSize=1000Player2
: IDENTITY 전략 사용.- 아래와 같이 Spring 통합 테스트로
saveAll()
메서드를 사용해서 batch-insert 를 시도했을 때 성능을 비교해본다.hibernate.jdbc.batch_size:1000
으로 batch size를 설정했다.- 아래 표와 같이 엔티티의 수가 적을 때는 id 채번을 위해 추가 쿼리가 발생하여 TABLE 방식이 느리지만, 엔티티 수가 많을 수록 기하급수적으로 IDENTITY 방식의 처리 시간이 느려지는 것을 확인할 수 있다.
n(엔티티 수) | TABLE(ms) | IDENTITY(ms) | 증가 비율 |
---|
1 | 151 | 92 | 0.61 |
2 | 225 | 94 | 0.42 |
10 | 220 | 190 | 0.86 |
50 | 233 | 905 | 3.88 |
250 | 296 | 3640 | 12.3 |
500 | 364 | 6963 | 19.13 |
1000 | 428 | 13417 | 31.35 |
5000 | 1179 | 60513 | 51.33 |
- 적은 개수를 insert 할 때는 절대적은 ms 차이가 크게 나는것은 아니지만, 개수가 늘어날 수록 IDENTITY는 기하급수적으로 느려지고 있었다.
- 직접 테스트해본 결과를 믿고 TABLE 방식을 사용하고자 한다.
참고 자료#
comments powered by