Database/Real MySQL Season1 ,2
14) UUID 사용 주의사항
Tony Lim
2024. 10. 10. 18:26
UUID Version
- Version 1,2
- Timestamp 기반의 UUID 생성
- 별도의 unique 한 값 입력없이 생성 가능
- version 3,5
- name과 namespace의 MD5 또는 SHA-1 해시 기반의 UUID 생성
- 생성시 unique한 입력을 필요로 한다.
- version 4
- 완전 랜덤한 UUID 생성
- Timestamp의 비트 순서가 바뀌어서 UUID에 배치된다.
- 7.5 바이트를 쪼개서 순서를 재배열해서 만들어진다.
- 생성시점이 동일해도 , 정렬 순서가 일치하지는 않는다.
UUID version-1의 타임스탬프는 100 나노초 단위로 1씩 증가 (각 row의 term을 말하는것이다.)
위 사진은 시간대별 UUID 값이다. 7분 10여초 단위로 첫번째 파트가 리셋된는 것을 알 수 있다.
UUID vs B-Tree
- UUID
- 시점과는 별개로 랜덤한 값을 생성한다 (7분쯤에 리셋됨으로 , 그 사이에는 단조 증가이긴함)
- 상대적으로 긴 문자열이다 (CHAR(32) or VARCHAR(32))
- B-Tree 인덱스의 성능 저해 요소
- 정렬되지 않은 키 값을 생성 한다 (정렬이 되어있어야 B-Tree인덱스과 효율적으로 동작한다 )
- 길이가 긴 키 값 (PK로 사용시 모든 Secondary Index에 영향을 미친다)
- 일반적으로 UUID 컬럼은 유니크 제약이 필요하다
- mysql에서는 인덱스의 변경은 changebuffer라는 공간을 이용해서 빠르게 처리하는데
- 유니크제약이 있으면 그것을 하지 못한다.
index자체가 크기가 엄청 크다 하더라도 , 실제로 쿼리를 위해 필요한 working set 이 작다면 괜찮다. (메모리에 올라가는)
보통 2년전의 데이터보다 최근 3개월 정도의 데이터가 훨씬 더 빈번하게 쓰인다. 하지만 UUID는 매번 랜덤한 값을 생성하기 때문에 prefix가 매번 달라질 수 있다. working set이 넓어진다고 볼 수 있다.
UUID vs BIGINT
- UUID: 32chars(VARCHAR) , 16bytes( BINARY)
- 보통 varchar를 많이 쓰게 된다.
- BIGINT: 8bytes
- 1억건 테이블 (10개의 인덱스를 가진 테이블의 PK인 경우)
- 단일 인덱스 크기 = 24GB vs 6GB
- 전체 인덱스 크기 = 264GB vs 66GB
- 필요 인스턴스
- db.r5.12xlarge : total_mem=384GB (buffer_pool = 277GB) $6,762
- db.r5.4xlarge : total_mem=128GB (buffer_pool = 89GB) $2,225
- 4개 인스턴스 사용시 비용 차이
- $ 18,032/month
- 앵간하면 BIGINT uid를 사용하는것이 좋아보인다
- snowflake-uid는 예측 불가하고 좋아보인다.
대체키 활용 (Hybrid)
내부적으로는 AutoIncrement 또는 TimeStamp 기반의 프라이머리 키
외부적으로는 UUID기반의 유니크 세컨드리 인덱스를 사용하는 방법