UUID?
Universally Unique Identifier
국제인터넷 표준 기구 IETF 에서 정식 표준으로 채택된 고유 식별자임.
128비트로 구성된 이진값
16진수 헥사데시멀 문자열(32바이트) 로 표현된다.
16진수 헥사데시멀?
한 자리로 15까지 표현할 수 있다.
0 ~ 9 다음에 A B C D E F 라는 문자를 사용한다
16개의 기호를 사용하는 것이다.
어떻게 구성되나
128비트 이진값을 16진수로 변환해서 표현한다.
이걸 32자리의 문자열로 나타낸다고 한다.
예를 들어
16진수 한 자리는 4비트(2 진수 4자리) 를 표현하고
128비트를 4비트씩 끊는다면 총 32개의 16진수 자리가 나온다.
DB에서 보통
CHAR(32) 혹은 VARCHAR(36) 와 같은 문자열 타입으로 저장된다고 한다.
UUID 버전
총 5개의 버전이 존재한다.
버전 1
타임 스탬프
와네트워크 카드의 맥어드레스 기반
으로 생성한다.단조 증가하는데 7분 주기로 초기화 된다고 한다.
7분 주기로 초기화되기에 장기적으로는 랜덤성을 유발한다.
단조 증가?
값이 지속적으로 같거나 증가하는 성질을 단조 증가라고 한다.
autoincrement 같은 설정이 단조 증가 값의 예시라고 볼 수 있다.
버전 2
잘 안씀
버전 3
이름과 네임스페이스 해시(MD5)
고유 문자열로 부터 생성된다고 한다.
버전 4
순수 랜덤 생성이다.
완전 랜덤임.
버전 5
이름과 네임스페이스 해시(SHA-1)
고유 문자열로부터 생성된다.
UUID - B-Tree Index 문제점
본질적으로 UUID 는 랜덤 값이기에
B-Tree 구조에 비효율적이다.
UUID 를 유니크 컬럼으로 사용하는 경우 MySQL 의 Change Buffer도 사용이 불가능하다.
UUID 의 무작위성(Randomness) 로 인하여 인덱스의 높은 분산성이 발생한다.
Change Buffer 의 기본 원리부터 따지고 들면
InnoDB 스토리지 엔진의 경우 성능 향상을 위해
Change Buffer
라는 구조를 사용한다.변경 버퍼는
세컨더리 인덱스(보조 인덱스) 에 대해 Insert, Update, Delete 작업을 하는 경우
인덱스 변경을 곧바로 디스크에 반영하지 않고 메모리에 임시 저장했다가
나중에 일괄적으로 처리(Batch Processing) 해서
디스크 접근 횟수를 줄이는 방식
이다.
변경 버퍼는
보조 인덱스
에만 적용이 가능하다.클러스터드 인덱스(PK) 에는 적용되지 않는다.
Change Buffer 사용 조건
효율적으로 동작하려면
보조 인덱스에 삽입할 데이터들이
국지적으로
+집중적으로
배치되어 있어야 한다변경되는 데이터들이 특정 페이지(Page) 에 밀집된 형태로 변경이 발생해야 메모리에서 다량의 변경을 일괄 처리함으로써 디스크 접근 횟수를 현저히 줄일 수 있음.
왜 문제가 되냐?
UUID 의 분산성때문에
UUID 삽입시 마다
무작위한 위치의 인덱스 페이지
에 접근해야 한다.매번 인덱스 페이지를 디스크에서 로드
OR업데이트
해야하는 상황이 발생한다.디스크 I/O 비용이 증가해 .. 변경 버퍼의 장점을 누릴 수 없고
성능의 저하가 발생한다.
UUID 를 PK 로 설정하면 보조 인덱스 비대화가 발생하여 성능이 저하된다.
위 주석 참고
최근 데이터 위주의 위킹셋 특성과 맞지 않는다
인덱스 워킹셋 크기 증가로 메모리의 효율이 감소한다.
디스크 IO 가 증대된다.
UUID 컬럼 길이 문제
16바이트 이진 값이지만, 실제로 32바이트 문자열로 저장하는 경우가 많다
컬럼 길이로 인하여 메모리와 인덱스 공간 차지가 증가된다.
비교(1억건 테이블 기준)
8바이트 정수 PK ; 약 6GB
32바이트 문자열 PK ; 약 24GB
보조 인덱스도 커지면서 전체적인 인덱스 크기가 급증한다.
AWS 인스턴스 기준으로 최대 18,000$ 정도의 월 비용 차이가 발생한다고 한다.
UUID 대안
Auto Increment
단조 값이지만, 외부 노출시 문제가 있다
Snowflake / Sonyflake
분산 시스템에서 중복되지 않는 고유 ID 를 생성하는 방식 중에 하나이다.
구성 3요소
타임 스탬프
과거 특정 시점(보통 서비스 시작일) 기준으로 한 경과 시간을
밀리초(ms) 단위
로 표현한다.시간이 흐름에 따라 숫자가 점점 커진다.
단조 값을 가질 수 있다는 장점이 있다.
머신 노드 ID
분산 시스템에서 여러 서버(노드) 가 동시에 ID 를 생성한다
서로 다른 서버가 동시에 같은 타임스탬프에 ID 를 생성하더라도
서버 간 충돌을 방지
할 수 있다.예시
서버 1:
001
서버 2:
010
서버 3:
011
이런식으로 서버별 머신 ID 를 부여할 수 있음.
시퀀스 번호
같은 서버에서 같은 밀리초(ms) 에 여러 개의 ID 가 발급될 수 있기에
단조증가하는 시퀀스 번호를 추가하여 충돌 방지함.
같은 서버에서 1234ms 의 타임스탬프에 3개의 ID 가 필요한 경우
1,234 ms | 001 | 0001
1,234 ms | 001 | 0002
1,234 ms | 001 | 0003
Real MySql 저자가 추천하는 데이터 모델링 방법
UUID 의 필요성에 대해 검토해라
내부적인 식별자는 auto increment 나 Snowflake / Sonyflake 를 사용해라
UUID 가 필수인 경우에는 PK 로 사용하지말고
별도의 컬럼으로 사용해서 테이블 성능을 유지하도록 해라.