UUID 단점 중 하나
UUID는 무작위로 값을 생성하기 때문에 순서가 보장되지 않는다.
이런 이유로 데이터베이스에서 UUID 값을 인덱스로 사용한다면 인덱싱이 어려울 수 있다.
TSID로 해결
UUID 인덱싱의 어려움을 해결할 수 있는 방법은 정렬을 하는 것이다.
시간 기반으로 정렬되고 중복되지 않는 고유한 식별자인 TSID를 이용하면 어느정도 해결할 수 있어 보인다.
사용 방법

하이버네이트의 UuidGenerator 어노테이션을 사용하면 손쉽게 TSID를 생성할 수 있다.
(하이버네이트 6.0 버전 이상 사용 가능)
TIME Enum 값을 보면 시간과 IP 기반으로 생성한다는 것을 확인할 수 있다.
이는 다수의 인스턴스 환경에서 같은 시간에 접근해도 고유한 값을 가질 수 있다는 것을 의미하는 것 같다.
적용
@ToString
@Entity
public class UUIDEntity {
@UuidGenerator(style = UuidGenerator.Style.TIME)
@Id @GeneratedValue
private UUID id;
}
public interface UUIDRepository extends JpaRepository<UUIDEntity, UUID> {
}
테스트
- 멀티 쓰레드 환경에서 사용이 가능한지 확인
- 정렬된 ID인지 확인
@DataJpaTest
class UUIDEntityTest {
@Autowired
UUIDRepository UUIDRepository;
@DisplayName("1000개 생성 동시성 테스트")
@Test
void createTest() throws InterruptedException {
CountDownLatch countDownLatch = new CountDownLatch(1000); // latch를 1000으로 설정
ExecutorService executorService = Executors.newFixedThreadPool(32); // 쓰레드 풀 생성
for (int i = 0; i < countDownLatch.getCount(); i++) {
executorService.submit(() -> {
// 쓰레드 동작
UUIDRepository.save(new UUIDEntity()); // Entity 저장
countDownLatch.countDown(); // latch를 1씩 감소
});
}
countDownLatch.await(); // // latch가 0에 도달할 때까지 쓰레드를 기다린다.
List<UUIDEntity> tsids = UUIDRepository.findAll();
// 1000개의 고유한 값들이 잘 들어갔는지 확인
assertThat(tsids).hasSize(1000);
tsids.forEach(System.out::println);
}
}


참고
- https://www.youtube.com/watch?v=1WT6oxchM9M
- https://thorben-janssen.com/generate-uuids-primary-keys-hibernate/
How to generate UUIDs as primary keys with Hibernate
If you decide to use UUIDs as primary keys, Hibernate can generate them based on IETF RFC 4122 version 1 and version 4.
thorben-janssen.com