Representação interna do SQL Server UniqueIdentifier / GUID

17

Um colega meu me enviou uma pergunta interessante, que não posso explicar inteiramente.

Ele executou algum código (incluído abaixo) e obteve resultados inesperados.

Basicamente, ao converter um UniqueIdentifier(ao qual me referirei Guiddaqui em diante) para um tipo binary(ou varbinary), a ordem da primeira metade do resultado é inversa, mas a segunda metade não.

Meu primeiro pensamento foi que a persistência do sistema foi a causa e que a Guidexibição foi preservada, mas o binaryformulário não é garantido.

Obviamente, este é um detalhe de implementação, mas eu queria saber se havia uma boa explicação para isso.

Código:

declare @guid uniqueidentifier = '8A737954-CBEC-40CE-A534-2AFFB5A0E207';
declare @binary binary(16) = (select convert(binary(16), @guid));
select @guid as [GUID], @binary as [Binary];

Resultados:

GUID                                 Binary
8A737954-CBEC-40CE-A534-2AFFB5A0E207 0x5479738AECCBCE40A5342AFFB5A0E207

Como você pode ver, a primeira metade do Guid(todo o caminho 40CE) é armazenada para trás em cada seção. Ou seja, a primeira seção Guidé para trás, depois a segunda seção e a terceira seção, mas a ordem das seções é preservada. Depois disso, as duas últimas seções são armazenadas na ordem exata em que aparecem na Guid.

Alguém pode explicar isso? (Um conjunto de teste maior está incluído abaixo.)

Código:

declare @guid_to_binary table
(
    [id] int identity(1,1),
    [guid] uniqueidentifier,
    [binary_conversion] binary(16)
);
declare @i int = 1;
while @i <= 100
begin
    insert into @guid_to_binary ( [guid] )
    select newid();
    set @i = @i + 1;
end
update @guid_to_binary
set binary_conversion = convert(binary(16), [guid]);
select * from @guid_to_binary;

Resultados:

id  guid                                    binary_conversion
1   EBA4DE58-D35F-46D9-9049-7939381F1A3B    0x58DEA4EB5FD3D94690497939381F1A3B
2   0445A8B7-B2F1-4B35-A4DC-92133570CD69    0xB7A84504F1B2354BA4DC92133570CD69
3   1006278C-1EB6-44A0-B8B0-3392A2EB0922    0x8C270610B61EA044B8B03392A2EB0922
4   EAB330DE-5984-49D6-9B84-F22823A3DB34    0xDE30B3EA8459D6499B84F22823A3DB34
5   25DA0D33-85A3-4AD8-9505-04B85DA6817F    0x330DDA25A385D84A950504B85DA6817F
6   B17B6263-C12B-46C2-BF30-D5AD0F3F765C    0x63627BB12BC1C246BF30D5AD0F3F765C
7   7B58993A-7207-45EC-AE72-B84D4BDE3C1A    0x3A99587B0772EC45AE72B84D4BDE3C1A
8   53772C37-80F6-4DBD-AE3F-3C105E857DFF    0x372C7753F680BD4DAE3F3C105E857DFF
9   D15F9608-CB18-4459-B57A-0D3ACC0421BF    0x08965FD118CB5944B57A0D3ACC0421BF
10  047B539A-80D4-4D22-9E9C-E3642E4AC5E5    0x9A537B04D480224D9E9CE3642E4AC5E5
11  467D192A-AAAF-403E-952D-82EB3B50C123    0x2A197D46AFAA3E40952D82EB3B50C123
12  88F2F0B5-D425-4B29-B774-487BFB30A4F4    0xB5F0F28825D4294BB774487BFB30A4F4
13  99ACBAC2-5F3C-4E57-A83E-088FE4FDA7E9    0xC2BAAC993C5F574EA83E088FE4FDA7E9
14  78D21192-F09B-4C14-B1FB-1DC0617CF23E    0x9211D2789BF0144CB1FB1DC0617CF23E
15  947BBFE5-B6F1-4833-9F44-4F4D6C45C742    0xE5BF7B94F1B633489F444F4D6C45C742
16  B528A36F-776B-4B43-85A2-A17D7D83BF07    0x6FA328B56B77434B85A2A17D7D83BF07
17  434D31D5-A659-475F-AC73-1D59479338F8    0xD5314D4359A65F47AC731D59479338F8
18  A9629EB2-1333-4C26-B5FA-2FB13961324C    0xB29E62A93313264CB5FA2FB13961324C
19  8D2F34CA-ADCB-4497-9568-33EBCE49DADA    0xCA342F8DCBAD9744956833EBCE49DADA
20  5A6A6C52-16AA-4CEF-B6DC-12C6AF40E1F5    0x526C6A5AAA16EF4CB6DC12C6AF40E1F5
21  ED48087D-C9F8-416B-A132-DFE6CBCAD1CF    0x7D0848EDF8C96B41A132DFE6CBCAD1CF
22  D623DF04-A284-4FA6-9CCA-3830E824EA79    0x04DF23D684A2A64F9CCA3830E824EA79
23  918E9032-535F-4FEE-9D28-FF756245A334    0x32908E915F53EE4F9D28FF756245A334
24  2307C209-DF28-4CB4-8A4B-3CB56C9A7094    0x09C2072328DFB44C8A4B3CB56C9A7094
25  9A86F2FE-353D-4BCE-81D0-9CB5BAB04FCA    0xFEF2869A3D35CE4B81D09CB5BAB04FCA
26  4C7D144E-E0E6-4D3C-BC42-D13EBC262096    0x4E147D4CE6E03C4DBC42D13EBC262096
27  AD0290F0-2A44-4FF8-AA82-B9693DF4AC16    0xF09002AD442AF84FAA82B9693DF4AC16
28  A4FC0E4E-0420-4841-AC75-19722D5C4050    0x4E0EFCA420044148AC7519722D5C4050
29  35F08F53-4E26-4CB1-B3AD-FF04898179E1    0x538FF035264EB14CB3ADFF04898179E1
30  5D4CE77D-6FE2-405B-AE1E-3DBB48C990BF    0x7DE74C5DE26F5B40AE1E3DBB48C990BF
31  019E9470-FA72-48D3-A6A3-7EC979BE7D5C    0x70949E0172FAD348A6A37EC979BE7D5C
32  841B906A-97DF-4326-8215-0CE9B0552288    0x6A901B84DF97264382150CE9B0552288
33  62922CA0-E540-490B-9B6D-258C0CF67CB3    0xA02C926240E50B499B6D258C0CF67CB3
34  607BC8CD-96A0-4460-835C-61CFF1DAB602    0xCDC87B60A0966044835C61CFF1DAB602
35  22ED2548-00C1-4E8C-AEA7-7C310CF9DFCD    0x4825ED22C1008C4EAEA77C310CF9DFCD
36  1B88FEB1-E96C-4AFA-BBFA-26A3444E4640    0xB1FE881B6CE9FA4ABBFA26A3444E4640
37  A7BFA1D4-2679-48D6-B4B5-1EB01AA93010    0xD4A1BFA77926D648B4B51EB01AA93010
38  22F3F3B3-D461-48D7-92F9-3BA6CFFFD513    0xB3F3F32261D4D74892F93BA6CFFFD513
39  22934FB8-443B-44C9-81FF-680C4C7D75F5    0xB84F93223B44C94481FF680C4C7D75F5
40  17B54276-0F8B-4FA6-8DDD-BAB02F55E6CC    0x7642B5178B0FA64F8DDDBAB02F55E6CC
41  8AA9D81D-330A-4E97-BE4B-3EA0F5937753    0x1DD8A98A0A33974EBE4B3EA0F5937753
42  50604CA3-5687-4C95-9562-277D29C67B18    0xA34C60508756954C9562277D29C67B18
43  C873B716-AAC5-4D35-BEFE-6B8069963DB8    0x16B773C8C5AA354DBEFE6B8069963DB8
44  E7638B30-A123-45A6-B93A-33DDBC359EA0    0x308B63E723A1A645B93A33DDBC359EA0
45  83F66044-5F98-45C2-A67D-01A1363FCFED    0x4460F683985FC245A67D01A1363FCFED
46  7478BC8F-E530-425B-B2CA-6A31C636F6B4    0x8FBC787430E55B42B2CA6A31C636F6B4
47  4881BB26-851E-4BF7-B62D-5A3DB3B0601C    0x26BB81481E85F74BB62D5A3DB3B0601C
48  C2A9ABB6-EF5E-4BF5-9574-81BEF6699D19    0xB6ABA9C25EEFF54B957481BEF6699D19
49  EB6637F4-08F3-4C4F-B46F-83CC74938562    0xF43766EBF3084F4CB46F83CC74938562
50  629839CE-806E-4F74-B897-A0F624A942F3    0xCE3998626E80744FB897A0F624A942F3
51  C63195B8-0458-46D0-BCA9-2012342145B5    0xB89531C65804D046BCA92012342145B5
52  08928C1B-B481-46D9-898F-84503C8B934C    0x1B8C920881B4D946898F84503C8B934C
53  3D9113FE-20CA-4136-8C6D-A18FAE50F6D0    0xFE13913DCA2036418C6DA18FAE50F6D0
54  83206C44-8F70-4952-83D5-80D8CCD02255    0x446C2083708F524983D580D8CCD02255
55  D591124E-5808-45F3-8A0E-F4BB68B733E5    0x4E1291D50858F3458A0EF4BB68B733E5
56  CE49BC3F-02AC-4536-B2FA-148845ED0EE0    0x3FBC49CEAC023645B2FA148845ED0EE0
57  F9663BCB-17FC-43B7-AF7F-B87518C17A4D    0xCB3B66F9FC17B743AF7FB87518C17A4D
58  BEE8F892-185D-49E7-8AA0-0F48E9404DC5    0x92F8E8BE5D18E7498AA00F48E9404DC5
59  DB9CC990-76C8-4F4B-A480-F82EA3BD3B6D    0x90C99CDBC8764B4FA480F82EA3BD3B6D
60  336ACE62-E185-4D1A-9217-E6A742AEA8A4    0x62CE6A3385E11A4D9217E6A742AEA8A4
61  075FBCEE-F473-40BB-82E2-D419036D9662    0xEEBC5F0773F4BB4082E2D419036D9662
62  255BD1CA-466C-4EBD-A769-0AEDA5ECDCBF    0xCAD15B256C46BD4EA7690AEDA5ECDCBF
63  604D2442-F88A-4034-9F8D-D0E36904A013    0x42244D608AF834409F8DD0E36904A013
64  0D58AAC6-47F1-4ACE-918C-AFFB639A45AB    0xC6AA580DF147CE4A918CAFFB639A45AB
65  8EE4C9E5-9C69-47A4-B4AB-6DF56FAFDD17    0xE5C9E48E699CA447B4AB6DF56FAFDD17
66  2EBA4B09-99EF-42A4-8BDF-C1F4EAEB37DD    0x094BBA2EEF99A4428BDFC1F4EAEB37DD
67  B25B5C1B-9233-411B-A781-D7F8427DB93A    0x1B5C5BB233921B41A781D7F8427DB93A
68  8747A125-F8DD-426F-8B31-A11DE7FED067    0x25A14787DDF86F428B31A11DE7FED067
69  744CE50A-5CCE-4A65-A502-3C165E7C1A13    0x0AE54C74CE5C654AA5023C165E7C1A13
70  AB990702-7B8C-427F-A1FF-22A2236B3BB2    0x020799AB8C7B7F42A1FF22A2236B3BB2
71  CDBFF8A2-7C4C-429C-AF0D-8D6AB1F376F6    0xA2F8BFCD4C7C9C42AF0D8D6AB1F376F6
72  0558FA3A-FF34-4A02-A32F-8017BBE0D98E    0x3AFA580534FF024AA32F8017BBE0D98E
73  C42E5C3B-7CEB-4B13-B0C7-B1A5436FA95F    0x3B5C2EC4EB7C134BB0C7B1A5436FA95F
74  B577B02E-2925-4F07-ABA0-FC981C126C0A    0x2EB077B52529074FABA0FC981C126C0A
75  20C77BE2-656B-4E4E-89AC-1E07D11B595F    0xE27BC7206B654E4E89AC1E07D11B595F
76  7192D091-B9B3-4D48-B44B-EC7ACDDEB800    0x91D09271B3B9484DB44BEC7ACDDEB800
77  6BD846C9-5EB8-40DE-92DB-844E3DF1827D    0xC946D86BB85EDE4092DB844E3DF1827D
78  009B2D21-1545-4C15-966E-D5EC31B45BE5    0x212D9B004515154C966ED5EC31B45BE5
79  7554AB43-1E1B-47CC-8AAA-248C86A590FA    0x43AB54751B1ECC478AAA248C86A590FA
80  6F46275B-F85F-426F-A9F6-6D923BA1F055    0x5B27466F5FF86F42A9F66D923BA1F055
81  63697CB0-68C8-4F91-9CCB-F28B04345F3A    0xB07C6963C868914F9CCBF28B04345F3A
82  7C3C36B0-7B71-4E8B-A14A-884CF61B3368    0xB0363C7C717B8B4EA14A884CF61B3368
83  8DBA33D7-83BC-4D74-A219-7AA0E25104FD    0xD733BA8DBC83744DA2197AA0E25104FD
84  917E3848-A028-41A4-9BC4-BA40625F1FF7    0x48387E9128A0A4419BC4BA40625F1FF7
85  9B87B6BA-7256-44F2-8AB7-516F8D906056    0xBAB6879B5672F2448AB7516F8D906056
86  6837D3BB-91FD-4E2A-AED5-6B8017004C54    0xBBD33768FD912A4EAED56B8017004C54
87  8E9FCD91-D9B4-465E-B1DF-2C3126FFA402    0x91CD9F8EB4D95E46B1DF2C3126FFA402
88  CB2E6016-5B09-40B5-AFD2-C989724DFED0    0x16602ECB095BB540AFD2C989724DFED0
89  F282E16A-068E-49D2-B65C-915214D06A04    0x6AE182F28E06D249B65C915214D06A04
90  6EDA33EB-8482-4BD8-9979-BB278C8D2C6F    0xEB33DA6E8284D84B9979BB278C8D2C6F
91  F4DC0E3B-B693-42C5-B5BD-07FC1A9AE8B9    0x3B0EDCF493B6C542B5BD07FC1A9AE8B9
92  24F12333-1B03-4EC4-A9A2-308A6F3CE996    0x3323F124031BC44EA9A2308A6F3CE996
93  5CCB94FC-F846-4EF3-ACF8-1DBAA0EB5405    0xFC94CB5C46F8F34EACF81DBAA0EB5405
94  9E8BC4B4-528F-42E3-B403-1A55F74420C3    0xB4C48B9E8F52E342B4031A55F74420C3
95  9F1BF452-31EC-486A-B572-4338319FC67E    0x52F41B9FEC316A48B5724338319FC67E
96  00B72F09-78AD-4BE5-9785-FA2939DE581A    0x092FB700AD78E54B9785FA2939DE581A
97  EC5A3AEF-3255-424D-8174-CBAEE0A2D243    0xEF3A5AEC55324D428174CBAEE0A2D243
98  48BC3E92-F3FA-47B8-881E-431D43118C99    0x923EBC48FAF3B847881E431D43118C99
99  C72A84F3-E961-4F6E-87AA-7A12D2EAD032    0xF3842AC761E96E4F87AA7A12D2EAD032
100 3F0E1666-BD80-4562-8FE3-CFA2009FDD08    0x66160E3F80BD62458FE3CFA2009FDD08
Der Kommissar
fonte
2
Embora eu não saiba que existe alguma aplicação prática valiosa desse conhecimento (porque o que você pode fazer sobre como o SQL Server implementa e armazena um GUID?), Pode haver alguns boatos interessantes para você aqui .
Aaron Bertrand

Respostas:

17

De acordo com o artigo da Wikipedia sobre identificador globalmente exclusivo (na seção "Codificação binária"), a implementação de GUIDs da Microsoft usa endianness "Nativo" para a primeira metade (os primeiros 8 bytes) e a codificação Big Endian para os segundos 8 bytes. O Microsoft Windows e o SQL Server são "Little Endian" devido à arquitetura Intel ser Little Endian, portanto, o "Nativo" implica "Little Endian". O gráfico a seguir é copiado desse artigo da Wikipedia:

Bits    Bytes   Name    Endianness
32      4       Data1   Native
16      2       Data2   Native
16      2       Data3   Native
64      8       Data4   Big

Em relação à Little Endianness do Microsoft SQL Server, a página Collation and Unicode Support MSDN declara:

Como a plataforma Intel é uma pequena arquitetura endian, os caracteres de código Unicode são sempre armazenados com troca de bytes.

Solomon Rutzky
fonte
2
Ok, mas por que eles fizeram isso?
Atario 24/11
1

Aqui está minha conclusão explicativa do uso prolongado e da revisão recente de vários padrões e materiais de referência.

Dado um formato ASCII de: {UInt32a-UInt16b-UInt16c-UInt16d-UInt48e}

ASCII: Representação ASCII char é a mesma para ambos UUID, e GUIDde dados e, portanto, é portátil.

MEMORY|LOCAL: A representação binária na memória ou no uso local é definida para usar o formato de endianness nativo como o formato de uso de memória mais eficiente, a partir dos documentos Apollo originais dos anos 80, como UInt64NativeEndian-UInt64BigEndian

PORTABLE: O formato de armazenamento binário-portátil é o local em que TODA a confusão existe entre UUID e GUID.

A GUIDsempre armazena os TEXTcampos de formato hexadecimal concatenados com os traços removidos como DOIS valores de 64 bits usando um UInt64[0]{LittleEndian}-UInt64[1]{BigEndian }layout. Tornar eficiente a conversão em qualquer plataforma, geralmente usando uma única instrução em um registro de 64 bits.

As UUIDregras de conversão binária portátil são divididas com base na variante2 versus todas as outras variantes. Para a variante2, segue o layout da GUID e, para todos os outros, armazena os três primeiros campos no formato ASCII como BigEndian de 32 bits, 16 bits, 16 bits, respectivamente, e os 6 bytes restantes, conforme aparecem no formato ASCII, o que equivale a 64 BitEndian (também conhecido como pedido de rede). Tornando muito menos eficiente o uso como representação binária, uma vez que a conversão requer várias instruções da máquina, mesmo para todas as formas não variantes2.

Nota: Existem muitos documentos e referências de padrões e eles são "inconsistentes" ou "em conflito" sobre como representar um valor da variante2 como um UUID binário-portátil.

Isso torna a forma binária GUID a forma preferida sobre a UUID-binária para conversão, pois é "menos" problemático para codificar / decodificar, pois a UUID exige a verificação dos bits de flag de variante de 3 msb no byte [8].

Observando ainda que a maioria das máquinas modernas usa little-endian nativo (as exceções são algumas máquinas de jogos e alguns equipamentos de rede), geralmente é muito mais eficiente usar o formato portátil-binário-GUID, pois ele mapeia precisamente para o local-binário nativo. forma de um UUID ou GUID.

smallscript
fonte