SQLite, UUID 기본 키 성능 함정 파헤치기
UUID4 기본 키는 SQLite의 B-tree 재균형 비용을 증가시켜 성능을 저하시킴
WITHOUT ROWID 테이블에서 UUID4 사용 시 기본 키 테이블 삽입 성능이 14-16배 하락함
시간 순서 기반 UUID7 사용 시 성능이 개선되나, 기본 정수 키보다는 느림
UUID 기본 키 사용 시 트레이드오프(Trade-off)를 고려한 신중한 접근이 필요함
UUID4와 SQLite B-tree의 성능 저하 메커니즘
커뮤니티에서는 UUID4의 무작위성이 SQLite의 클러스터형 인덱스(Clustered Index)인 B-tree에 무질서한 삽입을 유발한다고 지적한다. 이는 잦은 페이지 분할(Page Splitting)과 재균형 작업(Rebalancing Operations)을 초래하며, 결과적으로 디스크 I/O 증가와 삽입 성능 저하로 이어진다. 특히 WITHOUT ROWID 테이블에서 이러한 현상이 두드러져, 기본 정수 키 대비 14-16배 느린 삽입 속도를 보인다는 실험 결과가 제시되었다.
UUID7 도입을 통한 성능 개선 가능성
논의에서는 시간 순서 기반 UUID7이 UUID4의 무작위성 문제를 해결하여 B-tree 재균형 비용을 줄일 수 있다고 설명한다. 실험 결과, UUID7을 사용한 경우 삽입 성능이 UUID4 대비 크게 향상되었으나, 여전히 기본 정수 키(Integer Primary Key)보다는 느린 것으로 나타났다. 이는 UUID 자체의 16바이트 크기가 기본 정수 키(8바이트)보다 커서 발생하는 인덱스 크기 증가 및 캐시 효율성 저하 때문이라는 분석이 나온다.
WITHOUT ROWID 테이블과 ROWID 테이블의 트레이드오프
글에서는 WITHOUT ROWID 테이블이 암시적 rowid 인덱스를 제거하여 쓰기 증폭(Write Amplification)을 줄이는 장점이 있지만, 기본 키 자체가 클러스터형 인덱스가 되므로 UUID4 사용 시 성능 문제가 심화된다고 설명한다. 반면, 일반 ROWID 테이블은 순차적인 rowid를 클러스터형 인덱스로 활용하여 삽입 성능이 상대적으로 안정적이다. 하지만 이 경우 테이블에 두 개의 인덱스(rowid 및 사용자 정의 기본 키)가 존재하게 되어 쓰기 증폭이 발생할 수 있다는 점을 지적한다.
UUID 기본 키 사용 시 고려사항 및 대안
결론적으로, SQLite에서 UUID를 기본 키로 사용하는 것은 성능 트레이드오프(Performance Trade-off)를 수반한다고 강조한다. 특히 무작위 UUID4는 피해야 하며, UUID7이나 정렬 가능한 UUID(Sortable UUID) 사용을 고려해야 한다. 또한, 데이터베이스의 특성(Clustered Index)과 애플리케이션의 요구사항(Write Pattern)을 종합적으로 고려하여 가장 적합한 기본 키 전략을 선택해야 한다는 의견이 커뮤니티에서 제시된다.