# PostgreSQL와 UUID를 기본 키로 사용하는 것에 대해

> Clean Markdown view of GeekNews topic #15713. Use the original source for factual precision when an external source URL is present.

## Metadata

- GeekNews HTML: [https://news.hada.io/topic?id=15713](https://news.hada.io/topic?id=15713)
- GeekNews Markdown: [https://news.hada.io/topic/15713.md](https://news.hada.io/topic/15713.md)
- Type: GN+
- Author: [neo](https://news.hada.io/@neo)
- Published: 2024-07-06T13:34:06+09:00
- Updated: 2024-07-06T13:34:06+09:00
- Original source: [maciejwalkowiak.com](https://maciejwalkowiak.com/blog/postgres-uuid-primary-key/)
- Points: 21
- Comments: 4

## Summary

PostgreSQL에서 UUID를 기본 키로 사용할 때의 효율적인 방법을 다루며, 특히 UUID v7을 사용하면 삽입 성능이 향상될 수 있음을 실험을 통해 보여줍니다. 대규모 데이터셋이나 높은 트래픽이 예상되는 경우 최적화가 필요하며, TSID와 같은 다른 옵션도 고려해볼 만합니다. UUID의 크기와 성능 문제를 이해하고 최적의 선택을 할 수 있도록 돕는 유용한 정보를 제공합니다.

## Topic Body

- UUID는 데이터베이스 테이블 기본 키로 자주 사용됨  
  - 생성하기 쉽고 분산 시스템 간에 공유하기 쉬우며 고유성을 보장  
  - UUID의 크기를 고려할 때 이것이 올바른 선택인지 의문이 들지만, 우리가 결정할 수 없는 경우가 많음  
- 이 글은 "UUID가 키에 적합한 형식인가"에 초점을 맞추지 않고 PostgreSQL에서 UUID를 기본 키로 효율적으로 사용하는 방법에 대해 설명  
  
### PostgreSQL와 UUID를 기본 키로 사용하기  
  
- **UUID란?**  
  - UUID는 데이터베이스 테이블의 기본 키로 자주 사용됨  
  - 분산 시스템 간에 쉽게 공유 가능하며 고유성을 보장함  
  - UUID의 크기 때문에 적합한지 의문이 들 수 있지만, 선택의 여지가 없는 경우가 많음  
  
#### PostgreSQL에서 UUID 데이터 타입  
  
- **UUID를 문자열로 저장**  
  - PostgreSQL은 문자열을 저장하기 위한 `text` 데이터 타입을 제공함  
  - 그러나 `text` 타입은 UUID를 저장하기에 적합하지 않음  
  - PostgreSQL은 UUID를 위한 전용 데이터 타입 `uuid`를 제공함  
  - `uuid` 타입은 128비트 데이터 타입으로, 하나의 값을 저장하는 데 16바이트가 필요함  
  - `text` 타입은 1 또는 4바이트의 오버헤드가 추가됨  
  
- **실험 결과**  
  - 두 개의 테이블을 생성하여 비교: 하나는 `text` 타입, 다른 하나는 `uuid` 타입  
  - 10,000,000개의 행을 삽입한 후 테이블 크기와 인덱스 크기를 비교  
  - `text` 타입을 사용하는 테이블은 54% 더 크고, 인덱스 크기는 85% 더 큼  
  
#### UUID와 B-Tree 인덱스  
  
- **B-Tree 인덱스와 UUID**  
  - 랜덤 UUID는 B-Tree 인덱스에 적합하지 않음  
  - B-Tree 인덱스는 순서가 있는 값과 잘 작동함  
  - Java의 `UUID.randomUUID()`는 UUID v4를 반환하며, 이는 의사 랜덤 값임  
  - UUID v7은 시간 순서대로 정렬된 값을 생성하여 B-Tree 인덱스에 적합함  
  
- **UUID v7 사용**  
  - Java에서 UUID v7을 사용하려면 `java-uuid-generator` 라이브러리가 필요함  
  - UUID v7을 생성하면 삽입 성능이 향상될 수 있음  
  
#### UUID v7이 INSERT 성능에 미치는 영향  
  
- **실험**  
  - UUID v7을 사용하는 테이블을 생성하고, 10,000개의 행을 10번 삽입하여 성능을 측정  
  - 결과는 다소 무작위적이지만, UUID v7을 삽입하는 것이 약 2배 더 빠름  
  
#### 추가 읽을거리  
  
- PostgreSQL 17에서 UUID v7이 네이티브로 지원될 가능성 있음  
- UUID v7 형식에 대한 정보  
- UUID가 데이터베이스 기본 키로서의 성능에 미치는 영향  
  
#### 요약  
  
- **UUID의 길이 문제**  
  - 최적화가 이루어져도 UUID는 기본 키로서 최적의 타입이 아님  
  - 선택의 여지가 있다면 TSID와 같은 다른 옵션을 고려할 것  
  
- **최적화 필요성**  
  - 대규모 데이터셋이나 높은 트래픽이 예상된다면 최적화를 고려해야 함  
  - 기본 키 변경은 어려운 작업이므로 처음부터 올바르게 설정하는 것이 중요함  
  
- **주의사항**  
  - 필자는 PostgreSQL 전문가가 아니며, 배운 내용을 공유하는 것임  
  - 유용했다면 댓글이나 트위터를 통해 피드백을 주길 바람  
  
### GN⁺의 정리  
  
- 이 글은 PostgreSQL에서 UUID를 기본 키로 사용할 때의 효율적인 방법을 다룸  
- UUID v7을 사용하면 삽입 성능이 향상될 수 있음을 실험을 통해 보여줌  
- 대규모 데이터셋이나 높은 트래픽이 예상되는 경우 최적화가 필요함  
- TSID와 같은 다른 옵션도 고려해볼 만함

## Comments



### Comment 27088

- Author: savvykang
- Created: 2024-07-09T07:27:35+09:00
- Points: 1

uuid에 표준형식(16진수 + 하이픈) 대신 base62 인코딩을 바라는건 무리일까요?

### Comment 27047

- Author: qurare
- Created: 2024-07-08T09:18:44+09:00
- Points: 1

uuidv7 은 무적이다  
uuidv8+은 "신"이고

### Comment 27044

- Author: bbulbum
- Created: 2024-07-08T08:59:10+09:00
- Points: 1

가장 큰 허들은,, 인간친화적이지 않다는 것.. 저는 아직 많은부분에서 이부분이 필요하네요..

### Comment 27019

- Author: neo
- Created: 2024-07-06T13:34:07+09:00
- Points: 2

###### [Hacker News 의견](https://news.ycombinator.com/item?id=40884878) 
- B-tree 친화적인 기본 키로 bigserial을 사용하고, 외부 레코드 로케이터 옵션으로 문자열로 인코딩된 UUID를 고려할 것을 권장함
  - 비기술적인 사용자가 인용할 경우, PNR 스타일 로케이터와 같은 간단한 옵션을 먼저 고려할 것
  - 서비스나 애플리케이션의 스키마 내에서 PK 유형을 혼합하지 말 것
  - 고유 식별자로 UUIDv7을 사용할 때는 타임코드가 내재된 데이터에만 사용할 것
  - hashids를 사용하지 말 것; 암호화 품질이 없고 일상적인 사람들에게 친숙하지 않음
  - 인코딩 시 base64나 하이픈이 포함된 알파벳을 사용하지 말 것

- 데이터베이스 스키마 설계 시 관심사의 분리와 기계적 동조의 원칙을 염두에 둘 것

- Stripe의 타이핑된 랜덤 ID는 실제로 랜덤이 아님
  - 메타데이터, 포함된 타임스탬프, 샤드 및 참조 키, 버전 정보 등이 포함됨
  - 개인적으로 base58로 인코딩된 AES 암호화 bigserial+HMAC 로케이터를 선호함

- Postgres에서 랜덤 UUID는 큰 문제가 아님
  - UUID(16바이트)는 serial(4바이트)이나 bigserial(8바이트)보다 크지만, 전체 테이블 수준에서는 큰 문제가 아님

- Postgres에서 serial vs. random UUID vs. ordered UUID를 고려하기 전에 다른 많은 것들을 걱정해야 함

- 최근 Postgres PK로 ULID를 선택했으며, 이 기사에서 많은 도움을 받았음: [https://brandur.org/nanoglyphs/026-ids](https://brandur.org/nanoglyphs/026-ids)

- ULID를 선호하는 이유는 UUID 유형과 호환되며, 타임스탬프가 내장되어 있어 ID로 정렬하면 타임스탬프 순으로 정렬됨

- 비교에 'int64'도 포함되면 UUID와 전통적인 접근 방식의 오버헤드를 비교할 수 있어 좋을 것임

- 삽입 성능은 성능을 평가하는 나쁜 방법임
  - B-Tree 성능은 삽입 시 더 좋지만, 대규모 트랜잭션에서는 어떨지 의문임

- SQLite에서 UUID4가 선호되는 이유는 트랜잭션 잠금 동안 페이지 캐시 충돌 가능성이 적기 때문임
  - Postgres 시스템에서도 비슷하게 적용될 수 있음

- 정수 자동 증가 기본 키를 선호함
  - 이해하기 쉽고 정렬하기 간단함
  - 대규모 배치 프로젝트에서 마지막 기본 키를 저장하고 그보다 큰 모든 것을 가져올 수 있음

- UUIDv7 삽입 시간 벤치마크는 UUID 생성 시간을 포함함
  - 단순히 인덱스 업데이트 비용을 분리해서 보고 싶음

- PostgreSQL 17에서 UUIDv7 지원이 포함될 가능성이 낮음
  - 최근 작업에서 커미터가 제거되었고, 버전 17은 이미 기능 동결 상태임

- python-ulid를 사용하기 시작했으며, ULID가 UUID보다 우수함

- UUID v7 표준 링크가 오래되었으므로, RFC 9562를 참조할 것: [https://datatracker.ietf.org/doc/html/rfc9562](https://datatracker.ietf.org/doc/html/rfc9562)
