Recentemente, herdei um banco de dados do SQL Server que usa em BINARY(16)
vez de UNIQUEIDENTIFIER
armazenar Guids. Faz isso para tudo, incluindo chaves primárias.
Devo me preocupar?
sql-server
migration
uuid
Jonathan Allen
fonte
fonte
Respostas:
Bem, há algumas coisas aqui que são um pouco preocupantes.
Primeiro: embora seja verdade que a
UNIQUEIDENTIFIER
(ieGuid
) seja um valor binário de 16 bytes, também é verdade que:INT
podem ser armazenadosBINARY(4)
,DATETIME
podem ser armazenadosBINARY(8)
etc), portanto, o nº 2 ↴sysname
como um alias paraNVARCHAR(128)
).As três diferenças comportamentais que posso encontrar são:
Comparar
UNIQUEIDENTIFIER
valores no SQL Server, para o bem ou para o mal, na verdade não é feito da mesma maneira que compararBINARY(16)
valores. De acordo com a página do MSDN para comparar valores GUID e uniqueidentifier , ao compararUNIQUEIDENTIFIER
valores no SQL Server:Embora esses valores não sejam classificados com frequência, há uma pequena diferença entre esses dois tipos. De acordo com a página do MSDN para uniqueidentifier :
Como existem diferenças na maneira como os valores GUID são manipulados entre o SQL Server e o .NET (observados na página "Comparando GUID e valores exclusivos do identificador", acima), extrair esses dados do SQL Server para o código do aplicativo pode não ser tratado adequadamente em o código do aplicativo, se for necessário emular o comportamento de comparação do SQL Server. Esse comportamento pode ser emulado através da conversão para a
SqlGuid
, mas um desenvolvedor saberia fazer isso?Segundo: baseado na seguinte declaração
Em geral, eu me preocuparia com o desempenho do sistema usando GUIDs como PKs em vez de como Chaves Alternativas, além de usar um
INT
ou mesmoBIGINT
como PK. E ainda mais preocupado se essas PKs de GUID são os índices agrupados.ATUALIZAR
O comentário a seguir, feito pelo OP na resposta de @ Rob, traz uma preocupação adicional:
Os GUIDs podem ser armazenados em 2 formatos binários diferentes . Portanto, pode haver motivos de preocupação, dependendo de:
O problema com o qual a representação binária foi gerada tem a ver com a ordem de bytes dos 3 primeiros dos 4 "campos". Se você seguir o link acima para o artigo da Wikipedia, verá que o RFC 4122 especifica o uso da codificação "Big Endian" para todos os 4 campos, mas os GUIDs da Microsoft especificam o uso do Endianness "Nativo". Bem, a arquitetura da Intel é Little Endian, portanto, a ordem de bytes para os três primeiros campos é revertida dos sistemas após o RFC (assim como os GUIDs no estilo da Microsoft gerados nos sistemas Big Endian). O primeiro campo, "Dados 1", é de 4 bytes. Em um Endianness seria representado como (hipoteticamente)
0x01020304
. Mas no outro Endianness seria0x04030201
. Então, se o banco de dados atual 'BINARY(16)
essa representação binária foi gerada em um sistema após a RFC e, em seguida, converter os dados atualmente noBINARY(16)
campo emUNIQUEIDENTIFIER
resultará em um GUID diferente do que foi criado originalmente. Isso realmente não representa um problema se os valores nunca saírem do banco de dados e os valores são sempre comparados para igualdade e não para ordem.A preocupação com o pedido é simplesmente que eles não estarão na mesma ordem após a conversão para
UNIQUEIDENTIFIER
. Felizmente, se o sistema original realmente era o MySQL, o pedido nunca foi feito na representação binária em primeiro lugar, já que o MySQL possui apenas uma representação de string do UUID .A preocupação com os valores das strings sendo usadas fora do banco de dados é mais séria, novamente, se a representação binária foi gerada fora do Windows / SQL Server. Como a ordem dos bytes é potencialmente diferente, o mesmo GUID na forma de sequência resultaria em 2 representações binárias diferentes, dependendo de onde a conversão ocorreu. Se o código do aplicativo ou os clientes receberem um GUID em forma de sequência como
ABC
proveniente de uma forma binária de123
e a representação binária for gerada em um sistema após a RFC, a mesma representação binária (ou seja123
) será convertida em uma forma de sequênciaDEF
quando convertida em aUNIQUEIDENTIFIER
. Da mesma forma, a forma original da stringABC
seria convertida em uma forma binária de456
quando convertida em aUNIQUEIDENTIFIER
.Portanto, se os GUIDs nunca saírem do banco de dados, não haverá muito o que se preocupar fora do pedido. Ou, se a importação do MySQL foi feita convertendo a forma de string (ou seja
FCCEC3D8-22A0-4C8A-BF35-EC18227C9F40
), isso pode estar ok. Senão, se esses GUIDs foram fornecidos aos clientes ou no código do aplicativo, você pode testar para ver como eles convertem obtendo um e convertendo viaSELECT CONVERT(UNIQUEIDENTIFIER, 'value found outside of the database');
e veja se você encontra o registro esperado. Se você não conseguir corresponder os registros, talvez seja necessário manter os campos comoBINARY(16)
.Com toda a probabilidade, não haverá um problema, mas estou mencionando isso porque, nas condições certas, pode haver um problema.
E como novos GUIDs são inseridos? Gerado no código do aplicativo?
ATUALIZAÇÃO 2
Se a explicação anterior do possível problema relacionado à importação de representações binárias de GUID geradas em outro sistema foi um pouco (ou muito) confusa, espero que o seguinte seja um pouco mais claro:
Na saída mostrada acima, os valores "String" e "Binary" são do mesmo GUID. O valor abaixo da linha "Binário" é o mesmo valor da linha "Binário", mas formatado no mesmo estilo da linha "String" (ou seja, removido "0x" e adicionado os quatro traços). Comparando o primeiro e o terceiro valores, eles não são exatamente iguais, mas são muito próximos: as duas seções mais à direita são idênticas, mas as três seções mais à esquerda não são. Mas se você olhar atentamente, poderá ver que são os mesmos bytes em cada uma das três seções, apenas em uma ordem diferente. Pode ser mais fácil ver se mostro apenas as três primeiras seções e numero os bytes, para que seja mais fácil ver como a ordem deles difere entre as duas representações:
String = 1 5F 2 ED 3 23 4 BE - 5 E5 6 2C - 7 40 8 EE
Binário = 4 BE 3 23 2 ED 1 5F - 6 2C 5 E5 - 8 EE 7 40 (no Windows / SQL Server)
Portanto, em cada agrupamento, a ordem dos bytes é revertida, mas apenas no Windows e também no SQL Server. No entanto, em um sistema que adere à RFC, a representação binária espelhará a representação sting porque não haveria reversão da ordem dos bytes.
Como os dados foram trazidos para o SQL Server do MySQL? Aqui estão algumas opções:
Devoluções:
Supondo que fosse binário a binário direto (ou seja, o Convert # 2 acima), o GUID resultante, se convertido em um real
UNIQUEIDENTIFIER
, seria:Devoluções:
O que está errado. E isso nos deixa com três perguntas:
fonte
Você sempre pode estar preocupado. ;)
O sistema pode ter sido migrado de outro sistema que não suporta identificador exclusivo. Existem outros compromissos que você não conhece?
O designer pode não ter conhecimento sobre o tipo de identificador exclusivo. Que outras coisas eles não sabiam?
Tecnicamente, porém - não deve ser uma grande preocupação.
fonte