프로그래밍언어/MySQL or MariaDB 2017.10.12 15:10

늘 디비를 설계할 때 고민되는게, AUTO_INCREMENT 속성의 INT 또는 BIGINT 로 설정된 Primary Key 컬럼을 사용하는데요, 항상 의문이었습니다. Unsigned Integer 의 경우 0 에서 4,294,967,295 까지이고, Unsigned Big Integer 는 0 에서 18,446,744,073,709,551,615 까지입니다. 사실 BIGINT 로 해도 해당 모델을 사용하는 어플리케이션이 먼저 죽으면 죽었지 이게 먼저 채워질리는 없어 라고 생각하며 AUTO_INCREMENT flag 를 사용한 BIGINT 속성의 Primary Key를 늘 사용해 오다가, 갑자기 구글처럼 세계의 모든 블로그의 포스트를 URL 별로 저장하면 이게 가능할까? 였었습니다.

고유한 식별자에 대해 검색해보니, UUID 라는 것을 알게 되었습니다. Universally unique identifier 라는 일반적으로 널리 쓰이는 고유 식별자라는데 GUID 라고도 부른다고 하네요. 128 비트 숫자로 이루어진 고유 아이디라는 건데, 그렇다면 이것을 사용하게 되면 어느 정도의 확률로 중복될 수 있는지 찾아보았습니다. (수학에 재능이 없어요 저는 ㅋㅋ)

위키에 보시면, collision 항목에 상세히 설명이 되어 있네요. 간단하게 요약하자면, 2.71 * 10^18 개의 UUID를 생성했을 때 최소 1개가 중복(충돌) 될 확률이 약 50% 정도네요. 다시 말해서 이 숫자는 초당 1 billon 만큼의 UUID를 85년동안 생성해야 최소 1개가 중복된다라는 뜻같네요. (나중에 빅데이터를 하게 될 때 꼭 검증해봐야할 문제인거 같습니다.)

어찌됐든, 억지로 중복된 값을 만들려면 저장소 용량이 45 엑사바이트(exabytes) 이상이 되어야 하겠네요.

자세한 내용은 UUID 위키를 보시면 상세히 알 수 있어요. (제가 멍청한건 안비밀)

그럼 원래의 목적대로 MariaDB에서 UUID를 Primary Key 사용하는 법을 알아보겠습니다.

우선은 UUID는 이렇게 생겼어요:

MariaDB [test]> select uuid();
+--------------------------------------+
| uuid()                               |
+--------------------------------------+
| f189f4ae-af11-11e7-b252-186590cec0c1 |
+--------------------------------------+
1 row in set (0.00 sec)

그렇다면 CHAR(36) 으로 컬럼을 생성해서 사용해도 되지만, 식별자에 36bytes를 소모하는건 썩 마음에 들지 않습니다. 그래서 또 검색을 해보니 있네요.

최적화 방법은:

  • ‘-‘ 제거
  • hex digit 을 숫자(byte)로 변환

예제:

테이블을 생성해요.

CREATE TABLE `Users` (
  id BINARY(16) NOT NULL, 
  user VARCHAR(15) NOT NULL ,
  PRIMARY KEY (id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

레코드를 입력해요.

INSERT INTO Users (id, user) VALUES (UNHEX(REPLACE(UUID(),'-','')), 'Jimmy');

검색해보죠.

MariaDB [test]> select * from Users;
+------------------+-------+
| id               | user  |
+------------------+-------+
| �r"���Re����          | Jimmy |
+------------------+-------+
1 row in set (0.00 sec)

이쁘지 않네요. 이쁘게 출력해볼까요.

MariaDB [test]> select hex(id), user from Users;
+----------------------------------+-------+
| hex(id)                          | user  |
+----------------------------------+-------+
| D8720522AEFF11E7B252186590CEC0C1 | Jimmy |
+----------------------------------+-------+
1 row in set (0.00 sec)

이렇게 UUID로 PK를 만들 수 있습니다.

참고:

태그들 , , , , ,