JPA - MySQL에서 UUID column 사용시 유의점

Tony·2023년 5월 14일

Database

목록 보기
2/2

사전 지식

  • JPA의 ddl-auto기능을 이용하여 테이블을 만들때, 컬럼(Column) 타입의 기본 길이는 255입니다.
  • UUID의 경우 32개의 16진수 수와 4개의 하이픈(-)으로 이루어져 있습니다.
  • RFC에 따르면, 5종류의 UUID가 있으나 흔히 사용되는 것은 UUIDv1와 UUIDv4입니다.

UUIDv1

현재 timestamp와 로컬 MAC 주소나 IP 주소를 기반으로 생성되는 UUID입니다.

UUIDv4

난수(random-number)을 기반으로 생성된 UUID입니다.

MySQL에서의 UUID

PostgreSQL의 경우 UUID타입(16 바이트)을 지원합니다. 하지만, MySQL(InnoDB)의 경우 UUID타입을 직접 지원하지 않습니다. 그 대신에, char/varchar타입으로 저장합니다.

char/varchar로 저장할 경우

char로 저장할 경우, 반드시 char(36)로 컬럼을 만들어야합니다. 36보다 길이를 널널하게 설정하면, MySQL는 남는 길이는 0으로 패딩처리합니다. 따라서, 나중에 해당 UUID로 레코드를 찾으려할때, 아무 레코드도 반환하지 않을 것입니다.
varchar의 경우, 가변길이이기 때문에 길이가 남는다고 패딩하지 않습니다.
MySQL의 경우 utf8 대신에 utf8mb4 charset을 사용합니다. utf8mb4 charset의 문자 하나는 1~4바이트를 차지합니다. 따라서, UUID는 최악의 경우 4 * 36 = 144 바이트를 차지하게 됩니다. (varchar의 경우 prefix에 문자 길이(1~2바이트)를 표기하기 때문에 최대 146 바이트를 차지하게 될 수도 있습니다.)

binary로 저장할 경우

binary란 binary string을 의미합니다. UUID의 경우 16진수로 이루어져 있으므로, binary string을 사용하면 숫자 2개를 1 바이트로 표현할 수 있습니다. 따라서, binary타입으로 저장한다면 16바이트만 차지하게 됩니다.
JPA를 사용할 시, UUID는 기본적으로 binary string으로 저장됩니다. 따라서, MySQL을 사용할 시에 길이를 표시하는 것만 기억하면됩니다. binary또한, char과 동일하게 남는 부분은 0x00로 패딩하기 때문입니다.(참고로 varbinary는 패딩하지 않습니다.)

MySQL에는 UUID_TO_BIN(), BIN_TO_UUID() 함수가 있습니다. 해당 함수들에는 swap_flag가 존재하는데, 이 플래그를 1로 세팅하면 time-low, time-high 부분을 뒤바꾸어준다고 합니다. 그럼으로써, InnoDB에서 생성되는 UUIDv1 값들이 오름차순이 되도록 만들 수 있습니다. (오름차순이 보장되는 것이 아니라, 대부분 오름차순으로 생성됩니다.)
B-Tree 구조에서 오름차순으로 레코드가 삽입되면 효율적인 삽입 처리가 가능하므로, 해당 함수들을 잘 활용하면 성능 향상을 이룰 수 있을 것입니다. DBMS 함수를 사용해야하므로 JPA에서는 구현하기가 어려워 보입니다. (Hibernate에서는 UUIDGenerator를 제공하지만, 클라이언트측에서 UUID를 만들기 때문에 UUID_TO_BIN()를 사용할 수 있다고 가정하더라도 오름차순을 만들 수 없습니다.(클라이언트마다 MAC주소/IP주소 값이 다르기 때문))

Reference

https://blogs.oracle.com/mysql/post/mysql-uuids
https://dev.mysql.com/doc/refman/8.0/en

0개의 댓글