[mysql] MySQL 테이블에 GUID를 어떻게 저장해야합니까?

varchar (36)를 사용하거나 더 좋은 방법이 있습니까?



답변

내 DBA는 객체에 GUID를 저장하는 가장 좋은 방법에 대해 물었을 때 Integer로 4 바이트로 같은 일을 할 수있을 때 16 바이트를 저장 해야하는 이유를 물었습니다. 그가 저에게 그 도전을 줬기 때문에 나는 그것을 언급하기에 좋은 때라고 생각했습니다. 그 말은 …

스토리지 공간을 최대한 활용하려면 guid를 CHAR (16) 이진으로 저장할 수 있습니다.


답변

나는 그것을 char (36)로 저장할 것이다.


답변

ThaBadDawg의 대답에 덧붙여,이 편리한 기능을 사용하여 현명한 동료에게 감사하십시오 .36 길이의 문자열에서 16의 바이트 배열로 되돌립니다.

DELIMITER $$

CREATE FUNCTION `GuidToBinary`(
    $Data VARCHAR(36)
) RETURNS binary(16)
DETERMINISTIC
NO SQL
BEGIN
    DECLARE $Result BINARY(16) DEFAULT NULL;
    IF $Data IS NOT NULL THEN
        SET $Data = REPLACE($Data,'-','');
        SET $Result =
            CONCAT( UNHEX(SUBSTRING($Data,7,2)), UNHEX(SUBSTRING($Data,5,2)),
                    UNHEX(SUBSTRING($Data,3,2)), UNHEX(SUBSTRING($Data,1,2)),
                    UNHEX(SUBSTRING($Data,11,2)),UNHEX(SUBSTRING($Data,9,2)),
                    UNHEX(SUBSTRING($Data,15,2)),UNHEX(SUBSTRING($Data,13,2)),
                    UNHEX(SUBSTRING($Data,17,16)));
    END IF;
    RETURN $Result;
END

$$

CREATE FUNCTION `ToGuid`(
    $Data BINARY(16)
) RETURNS char(36) CHARSET utf8
DETERMINISTIC
NO SQL
BEGIN
    DECLARE $Result CHAR(36) DEFAULT NULL;
    IF $Data IS NOT NULL THEN
        SET $Result =
            CONCAT(
                HEX(SUBSTRING($Data,4,1)), HEX(SUBSTRING($Data,3,1)),
                HEX(SUBSTRING($Data,2,1)), HEX(SUBSTRING($Data,1,1)), '-', 
                HEX(SUBSTRING($Data,6,1)), HEX(SUBSTRING($Data,5,1)), '-',
                HEX(SUBSTRING($Data,8,1)), HEX(SUBSTRING($Data,7,1)), '-',
                HEX(SUBSTRING($Data,9,2)), '-', HEX(SUBSTRING($Data,11,6)));
    END IF;
    RETURN $Result;
END
$$

CHAR(16)실제로 BINARY(16)선호하는 맛을 선택하십시오.

코드를 더 잘 따르려면 아래의 숫자로 정렬 된 GUID를 예로 들어 보겠습니다. (잘못된 문자는 설명 목적으로 사용되며 각 위치마다 고유 한 문자가 사용됩니다.)이 함수는 우수한 인덱스 클러스터링을 위해 비트 순서를 달성하도록 바이트 순서를 변환합니다. 재정렬 된 guid가 예제 아래에 표시되어 있습니다.

12345678-9ABC-DEFG-HIJK-LMNOPQRSTUVW
78563412-BC9A-FGDE-HIJK-LMNOPQRSTUVW

대시가 제거되었습니다.

123456789ABCDEFGHIJKLMNOPQRSTUVW
78563412BC9AFGDEHIJKLMNOPQRSTUVW


답변

char (36)이 좋은 선택입니다. 또한 MySQL의 UUID () 함수를 사용하여 36 자 텍스트 형식 (하이픈이있는 16 진수)을 반환하여 db에서 이러한 ID를 검색하는 데 사용할 수 있습니다.


답변

“더 나은”은 최적화하는 대상에 따라 다릅니다.

스토리지 크기 / 성능 대 개발 용이성에 대해 얼마나 관심이 있습니까? 더 중요한 것은-충분한 GUID를 생성하거나 자주 가져 오는 것이 중요합니까?

대답이 “아니오”이면 char(36)충분하고 GUID를 저장 / 가져 오기가 매우 간단합니다. 그렇지 않으면 binary(16)합리적이지만 일반적인 문자열 표현에서 앞뒤로 변환하려면 MySQL 및 / 또는 프로그래밍 언어를 사용해야합니다.


답변

이진 (16)은 varchar (32)를 사용하는 것보다 좋습니다.


답변

KCD에 의해 게시 된 GuidToBinary 루틴은 GUID 문자열에서 타임 스탬프의 비트 레이아웃을 설명하도록 조정되어야합니다. 문자열이 uuid () mysql 루틴이 리턴 한 것과 같이 버전 1 UUID를 나타내는 경우 시간 구성 요소는 D를 제외하고 문자 1-G로 임베드됩니다.

12345678-9ABC-DEFG-HIJK-LMNOPQRSTUVW
12345678 = least significant 4 bytes of the timestamp in big endian order
9ABC     = middle 2 timestamp bytes in big endian
D        = 1 to signify a version 1 UUID
EFG      = most significant 12 bits of the timestamp in big endian

이진으로 변환 할 때 인덱싱에 가장 적합한 순서는 EFG9ABC12345678D + 나머지입니다.

빅 엔디안은 이미 최고의 이진 인덱스 바이트 순서를 생성하므로 12345678을 78563412로 바꾸지 않으려 고합니다. 그러나 가장 중요한 바이트를 더 낮은 바이트 앞으로 이동 시키길 원합니다. 따라서 EFG가 먼저 시작한 다음 중간 비트와 하위 비트가 이어집니다. 1 분 동안 uuid ()를 사용하여 12 개 정도의 UUID를 생성하면이 순서가 올바른 순위를 얻는 방법을 확인해야합니다.

select uuid(), 0
union
select uuid(), sleep(.001)
union
select uuid(), sleep(.010)
union
select uuid(), sleep(.100)
union
select uuid(), sleep(1)
union
select uuid(), sleep(10)
union
select uuid(), 0;

/* output */
6eec5eb6-9755-11e4-b981-feb7b39d48d6
6eec5f10-9755-11e4-b981-feb7b39d48d6
6eec8ddc-9755-11e4-b981-feb7b39d48d6
6eee30d0-9755-11e4-b981-feb7b39d48d6
6efda038-9755-11e4-b981-feb7b39d48d6
6f9641bf-9755-11e4-b981-feb7b39d48d6
758c3e3e-9755-11e4-b981-feb7b39d48d6 

처음 두 UUID는 가장 가까운 시간에 생성되었습니다. 그것들은 첫 번째 블록의 마지막 3 니블에서만 다릅니다. 이것들은 타임 스탬프에서 가장 중요하지 않은 비트이므로 인덱스 가능한 바이트 배열로 변환 할 때 오른쪽으로 푸시하려고합니다. 반대의 예로서, 마지막 ID가 가장 최신이지만, KCD의 스와핑 알고리즘은이를 3 번째 ID (3e 앞의 3e, 첫 번째 블록의 마지막 바이트) 앞에 둡니다.

올바른 색인 순서는 다음과 같습니다.

1e497556eec5eb6...
1e497556eec5f10...
1e497556eec8ddc...
1e497556eee30d0...
1e497556efda038...
1e497556f9641bf...
1e49755758c3e3e... 

지원 정보는이 기사를 참조하십시오 : http://mysql.rjweb.org/doc.php/uuid

*** 버전 니블을 타임 스탬프의 상위 12 비트에서 분리하지 않습니다. 이것은 귀하의 예에서 D 니블입니다. 방금 던졌습니다. 따라서 이진 시퀀스는 DEFG9ABC 등이됩니다. 이것은 색인 된 모든 UUID가 동일한 니블로 시작한다는 것을 의미합니다. 기사도 마찬가지입니다.