MySQL에서 주요 키를 UUID로 사용하는 것이 성능을 해칠 수 있는 이유
Mar 18, 2025
# Database
Grace Collins
Solutions Engineer · Leapcell

대규모 테이블에서 UUID를 기본 키로 사용하면 특히 데이터를 삽입하고 수정할 때 효율성 측면에서 성능 문제가 발생할 수 있습니다. 아래는 데이터 수정으로 인해 인덱스 새로 고침이 발생하는 이유와 문자 기반 기본 키가 덜 효율적인 이유를 포함하여 이에 대한 자세한 분석입니다.
UUID를 기본 키로 사용할 때의 문제점
UUID의 특징
- UUID는 128비트 문자열이며 일반적으로 36자로 표현됩니다(예:
550e8400-e29b-41d4-a716-446655440000
). - UUID는 전역적으로 고유하므로 분산 시스템에서 고유 식별자를 생성하는 데 적합합니다.
UUID를 기본 키로 사용할 때의 단점
-
낮은 인덱스 효율성
- 인덱스 크기: UUID는 문자열 유형이며 많은 공간(36바이트)을 차지하는 반면, 정수 기본 키(
BIGINT
와 같은)는 8바이트만 차지합니다. 인덱스가 클수록 스토리지 및 쿼리 효율성이 낮아집니다. - 인덱스 분할: UUID는 정렬되지 않았으므로 새 데이터를 삽입할 때 인덱스 트리의 빈번한 분할 및 재조정이 발생하여 성능에 영향을 줄 수 있습니다.
- 인덱스 크기: UUID는 문자열 유형이며 많은 공간(36바이트)을 차지하는 반면, 정수 기본 키(
-
저조한 삽입 성능
- 무작위성: UUID는 정렬되지 않았으므로 각 새 레코드가 인덱스 트리의 임의 위치에 삽입되어 인덱스 트리 조정이 빈번하게 발생할 수 있습니다.
- 페이지 분할: InnoDB 스토리지 엔진은 B+ 트리를 인덱스 구조로 사용합니다. 임의 삽입은 페이지 분할을 유발하여 디스크 I/O 작업을 증가시킬 수 있습니다.
-
저조한 쿼리 성능
- 낮은 비교 효율성: 문자열 비교는 정수 비교보다 느리며, 특히 대규모 테이블에서는 쿼리 성능이 크게 저하됩니다.
- 큰 인덱스 스캔 범위: UUID 인덱스는 더 많은 공간을 차지하므로 인덱스 스캔 범위가 증가하여 쿼리 효율성이 저하됩니다.
데이터 수정으로 인해 인덱스 새로 고침이 발생하는 이유
인덱스의 목적
- 인덱스는 쿼리 속도를 높이기 위해 생성된 데이터 구조(예: B+ 트리)입니다.
- 데이터를 수정할 때 데이터 일관성을 유지하려면 인덱스도 업데이트해야 합니다.
데이터 수정이 인덱스에 미치는 영향
-
기본 키 업데이트
- 기본 키 값이 수정되면 MySQL은 이전 기본 키 인덱스 레코드를 삭제하고 새 기본 키 인덱스 레코드를 삽입해야 합니다.
- 이 프로세스에는 인덱스 트리 조정이 필요하며 디스크 I/O 작업이 증가합니다.
-
기본 키가 아닌 열 업데이트
- 수정된 열이 인덱싱된 열(예: 고유 인덱스 또는 일반 인덱스)인 경우 MySQL은 해당 인덱스 레코드를 업데이트해야 합니다.
- 이 프로세스 역시 인덱스 트리 조정을 유발합니다.
UUID 기본 키의 추가 오버헤드
- UUID는 정렬되지 않았으므로 기본 키 값을 수정하면 새 값이 인덱스 트리의 다른 위치에 삽입되어 인덱스 트리 조정이 빈번하게 발생할 수 있습니다.
- 정렬된 기본 키(예: 자동 증가 ID)와 비교할 때 UUID 기본 키를 수정하는 데 더 많은 비용이 발생합니다.
문자 기반 기본 키가 효율성을 저하시키는 이유
큰 저장 공간
- 문자 기반 기본 키(예: UUID)는 정수 기본 키보다 더 많은 저장 공간을 차지합니다.
- 인덱스 크기는 쿼리 성능에 직접적인 영향을 미칩니다. 인덱스가 클수록 쿼리 중에 더 많은 디스크 I/O 작업이 필요합니다.
낮은 비교 효율성
- 문자열 비교는 정수 비교보다 느리며, 특히 대규모 테이블에서는 쿼리 성능이 크게 저하됩니다.
- 예를 들어
WHERE id = '550e8400-e29b-41d4-a716-446655440000'
는WHERE id = 12345
보다 효율성이 떨어집니다.
인덱스 분할
- 문자 기반 기본 키는 종종 정렬되지 않으므로 새 데이터를 삽입할 때 빈번한 인덱스 트리 분할 및 재조정이 발생하여 성능에 영향을 줄 수 있습니다.
UUID 기본 키의 성능을 최적화하는 방법
정렬된 UUID 사용
- 인덱스 분할 및 페이지 분할을 줄이려면 정렬된 UUID(UUIDv7과 같은)를 사용합니다.
- 정렬된 UUID는 타임스탬프를 기반으로 생성하여 삽입 순서를 보장할 수 있습니다.
UUID를 이진 형식으로 저장
- 저장 공간을 줄이려면 UUID를
CHAR(36)
대신BINARY(16)
으로 저장합니다.
CREATE TABLE users ( id BINARY(16) PRIMARY KEY, name VARCHAR(255) );
자동 증가 기본 키 + UUID 사용
- 자동 증가 기본 키를 물리적 기본 키로 사용하고 UUID를 논리적 기본 키로 사용합니다.
CREATE TABLE users ( id BIGINT AUTO_INCREMENT PRIMARY KEY, uuid CHAR(36) UNIQUE, name VARCHAR(255) );
분할된 테이블 사용
- 대규모 테이블을 분할하여 개별 인덱스 트리의 크기를 줄이고 쿼리 성능을 개선합니다.
요약
-
UUID를 기본 키로 사용할 때의 단점
- 낮은 인덱스 효율성, 저조한 삽입 및 쿼리 성능.
- 데이터를 수정할 때 인덱스 새로 고침이 빈번하게 발생하여 성능 저하가 발생합니다.
-
문자 기반 기본 키의 효율성이 낮은 이유
- 큰 저장 공간, 낮은 비교 효율성, 빈번한 인덱스 분할.
-
최적화 권장 사항
- 정렬된 UUID를 사용하거나 이진 형식으로 저장합니다.
- 자동 증가 기본 키와 UUID를 결합합니다.
- 대규모 테이블을 분할합니다.
백엔드 프로젝트 호스팅을 위한 최고의 선택, Leapcell입니다.
Leapcell은 웹 호스팅, 비동기 작업 및 Redis를 위한 차세대 서버리스 플랫폼입니다.
다국어 지원
- Node.js, Python, Go 또는 Rust로 개발하세요.
무제한 프로젝트를 무료로 배포하세요
- 사용량에 대해서만 비용을 지불합니다. 요청이나 수수료는 없습니다.
탁월한 비용 효율성
- 유휴 요금 없이 사용한 만큼 지불합니다.
- 예: $25로 평균 응답 시간 60ms에서 694만 건의 요청을 지원합니다.
간소화된 개발자 경험
- 손쉬운 설정을 위한 직관적인 UI.
- 완전 자동화된 CI/CD 파이프라인 및 GitOps 통합.
- 실행 가능한 통찰력을 위한 실시간 메트릭 및 로깅.
손쉬운 확장성 및 고성능
- 고도의 동시성을 쉽게 처리할 수 있는 자동 확장.
- 운영 오버헤드가 전혀 없습니다. 빌드에만 집중하세요.
설명서에서 자세히 알아보세요!
X에서 팔로우하세요: @LeapcellHQ