최근에 Guid를 저장 하는 BINARY(16)
대신 사용하는 SQL Server 데이터베이스를 상속했습니다 UNIQUEIDENTIFIER
. 기본 키를 포함한 모든 작업에 적용됩니다.
걱정해야합니까?
최근에 Guid를 저장 하는 BINARY(16)
대신 사용하는 SQL Server 데이터베이스를 상속했습니다 UNIQUEIDENTIFIER
. 기본 키를 포함한 모든 작업에 적용됩니다.
걱정해야합니까?
답변:
걱정해야합니까?
글쎄, 여기에 약간 관련된 몇 가지가 있습니다.
첫째 : a UNIQUEIDENTIFIER
(즉, Guid
)가 16 바이트 이진 값인 것이 사실이지만 다음과 같은 사항도 적용됩니다.
INT
으로 저장 될 수 있습니다 (예 :에 저장 가능 BINARY(4)
,에 DATETIME
저장 가능 BINARY(8)
등). # 2 ↴sysname
에 대한 별명 NVARCHAR(128)
).내가 찾을 수있는 세 가지 행동 차이는 다음과 같습니다.
UNIQUEIDENTIFIER
더 나은지 나쁜지에 대한 SQL Server의 값 비교 는 실제로 BINARY(16)
값 을 비교하는 것과 같은 방식으로 수행되지 않습니다 . SQL Server에서 값을 비교할 때 GUID 및 uniqueidentifier Value 비교 에 대한 MSDN 페이지에 따르면 UNIQUEIDENTIFIER
:
값의 마지막 6 바이트가 가장 중요합니다
이 값은 자주 정렬되지 않지만이 두 유형 간에는 약간의 차이가 있습니다. uniqueidentifier 에 대한 MSDN 페이지에 따르면 :
순서는 두 값의 비트 패턴을 비교하여 구현되지 않습니다.
SQL Server와 .NET 사이에서 GUID 값을 처리하는 방법 (위의 "GUID와 uniqueidentifier 값 비교"페이지에 설명되어 있음)에 차이가 있으므로 SQL Server에서이 데이터를 앱 코드로 가져 오는 것이 제대로 처리되지 않을 수 있습니다. SQL Server 비교 동작을 에뮬레이션해야하는 경우 앱 코드 이 동작은로 변환하여 에뮬레이션 할 수 SqlGuid
있지만 개발자가 알고 있어야합니까?
둘째 : 다음 진술에 근거
기본 키를 포함한 모든 작업에 적용됩니다.
대체 키 대신 GUID를 PK로 사용 INT
하거나 PK로 사용하여 시스템 성능에 일반적으로 관심이 있습니다 BIGINT
. 이러한 GUID PK가 클러스터형 인덱스인지에 대해서는 더욱 우려됩니다.
@Rob의 답변에 대한 OP의 의견은 다음과 같습니다.
그것은 MySQL에서 생각
GUID는 2 가지 이진 형식 으로 저장할 수 있습니다 . 따라서 다음에 따라 우려의 원인 이 있을 수 있습니다.
이진 표현이 생성되는 문제는 4 개의 "필드"중 첫 3 개의 바이트 순서와 관련이 있습니다. 위의 Wikipedia 기사 링크를 따라 가면 RFC 4122가 4 개 필드 모두에 대해 "Big Endian"인코딩을 사용하도록 지정하지만 Microsoft GUID는 "Native"엔디안을 사용하여 지정한다는 것을 알 수 있습니다. 인텔 아키텍처는 Little Endian이므로 처음 3 개의 필드에 대한 바이트 순서는 RFC를 따르는 시스템과 Big Endian 시스템에서 생성 된 Microsoft 스타일 GUID와 반대로 바뀝니다. 첫 번째 필드 인 "Data 1"은 4 바이트입니다. 한 엔디안에서는 (가설 적으로) 표현됩니다 0x01020304
. 그러나 다른 엔디안에서는 그럴 것입니다 0x04030201
. 현재 데이터베이스가BINARY(16)
이진 표현은 RFC를 따르는 시스템에서 생성 된 다음 현재 BINARY(16)
필드에있는 데이터를로 변환하면 UNIQUEIDENTIFIER
원래 작성된 것과 다른 GUID가됩니다. 이건 정말 문제를 제기하지 않는 경우 값이 데이터베이스를 떠난 적이 결코 및 값이 오직 주문 어떤지를하지 비교된다.
순서에 대한 문제는로 변환 한 후 순서가 동일하지 않다는 것입니다 UNIQUEIDENTIFIER
. 다행히도 원래 시스템이 실제로 MySQL이라면 MySQL에는 UUID 문자열 표현 만 있기 때문에 이진 표현에 대한 주문은 처음부터 이루어지지 않았습니다 .
이진 표현이 Windows / SQL Server 외부에서 생성 된 경우 데이터베이스 외부에서 사용되는 문자열 값에 대한 우려가 더 심각합니다. 바이트 순서가 잠재적으로 다르기 때문에 문자열 형식의 동일한 GUID는 변환이 발생한 위치에 따라 2 개의 다른 2 진 표현을 생성합니다. 응용 프로그램 코드 또는 고객이 같은 문자열 형태의 GUID를 주어진 경우 ABC
의 바이너리 형식에서 오는 123
및 은 RFC에 따라 시스템에서 생성 된 이진 표현, 다음 같은 이진 표현 (즉 것을 123
)의 스트링 형태로 변환 할 DEF
로 변환 할 때 UNIQUEIDENTIFIER
. 마찬가지로의 원래 문자열 형식은 ABC
의 이진 형식으로 456
변환됩니다 UNIQUEIDENTIFIER
.
따라서 GUID가 데이터베이스를 떠나지 않은 경우 주문 외부에 대해 걱정할 필요가 없습니다. 또는 문자열 형식을 변환하여 MySQL에서 가져 오기를 수행 한 경우 (예 : FCCEC3D8-22A0-4C8A-BF35-EC18227C9F40
괜찮음) 그렇지 않으면 해당 GUID가 고객 또는 앱 코드에 제공된 경우 하나를 가져 와서 변환 SELECT CONVERT(UNIQUEIDENTIFIER, 'value found outside of the database');
하여 예상되는 레코드를 찾는 지 여부를 테스트 할 수 있습니다 . 레코드를 일치시킬 수없는 경우 필드를로 유지해야합니다 BINARY(16)
.
모든 경우에 문제는 없지만 올바른 조건에서 문제가 발생할 수 있기 때문에 이것을 언급하고 있습니다.
어쨌든 새로운 GUID는 어떻게 삽입됩니까? 앱 코드에서 생성 되었습니까?
다른 시스템에서 생성 된 GUID의 이진 표현 가져 오기와 관련된 잠재적 문제에 대한 이전의 설명이 약간 혼란 스러우면 다음 사항이 좀 더 명확 해지기를 바랍니다.
DECLARE @GUID UNIQUEIDENTIFIER = NEWID();
SELECT @GUID AS [String], CONVERT(BINARY(16), @GUID) AS [Binary];
-- String = 5FED23BE-E52C-40EE-8F45-49664C9472FD
-- Binary = 0xBE23ED5F2CE5EE408F4549664C9472FD
-- BE23ED5F-2CE5-EE40-8F45-49664C9472FD
위에 표시된 출력에서 "String"및 "Binary"값은 동일한 GUID에서 가져옵니다. "Binary"행 아래의 값은 "Binary"행과 동일한 값이지만 "String"행과 같은 스타일로 형식이 지정됩니다 (예 : "0x"를 제거하고 네 개의 대시를 추가). 첫 번째와 세 번째 값을 비교하면 정확히 같지는 않지만 매우 가깝습니다. 가장 오른쪽 두 섹션은 동일하지만 가장 왼쪽 세 섹션은 다릅니다. 그러나 자세히 살펴보면 세 섹션의 각 바이트가 다른 순서로 동일한 바이트임을 알 수 있습니다. 처음 세 섹션 만 표시하는지 확인하고 바이트 수를 지정하면 두 표현간에 순서가 어떻게 다른지 쉽게 알 수 있습니다.
문자열 = 1 5F 2 ED 3 23 4 BE – 5 E5 6 2C – 7 40 8 EE
이진 = 4 BE 3 23 2 ED 1 5F – 6 2C 5 E5 – 8 EE 7 40 (Windows / SQL Server)
따라서 각 그룹 내에서 바이트 순서는 반대로 바뀌지 만 Windows 및 SQL Server 내에서만 바뀝니다. 그러나 RFC를 준수하는 시스템에서 바이트 순서의 반전이 없기 때문에 이진 표현은 찌르기 표현을 반영합니다.
데이터는 MySQL에서 SQL Server로 어떻게 가져 왔습니까? 다음은 몇 가지 선택 사항입니다.
SELECT CONVERT(BINARY(16), '5FED23BE-E52C-40EE-8F45-49664C9472FD'),
CONVERT(BINARY(16), 0x5FED23BEE52C40EE8F4549664C9472FD),
CONVERT(BINARY(16), CONVERT(UNIQUEIDENTIFIER, '5FED23BE-E52C-40EE-8F45-49664C9472FD'));
보고:
0x35464544323342452D453532432D3430
0x5FED23BEE52C40EE8F4549664C9472FD
0xBE23ED5F2CE5EE408F4549664C9472FD
이진을 이진에서 이진으로 가정하면 (예 : 위의 변환 # 2) 실제 GUID로 변환되는 경우 결과 GUID는 다음과 UNIQUEIDENTIFIER
같습니다.
SELECT CONVERT(UNIQUEIDENTIFIER, 0x5FED23BEE52C40EE8F4549664C9472FD);
보고:
BE23ED5F-2CE5-EE40-8F45-49664C9472FD
어느 것이 잘못 되었습니까? 그리고 그것은 우리에게 세 가지 질문을 남깁니다.
당신은 항상 걱정할 수 있습니다. ;)
시스템이 고유 식별자를 지원하지 않는 다른 시스템에서 마이그레이션되었을 수 있습니다. 모르는 다른 타협이 있습니까?
디자이너가 고유 식별자 유형에 대해 알지 못했을 수 있습니다. 그들이 모르는 다른 것들은 무엇입니까?
하지만 기술적으로는 큰 문제가되지 않습니다.