AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / dba / Perguntas / 126446
Accepted
Jonathan Allen
Jonathan Allen
Asked: 2016-01-18 01:12:42 +0800 CST2016-01-18 01:12:42 +0800 CST 2016-01-18 01:12:42 +0800 CST

Existe uma penalidade por usar BINARY(16) em vez de UNIQUEIDENTIFIER?

  • 772

Recentemente, herdei um banco de dados do SQL Server que usa BINARY(16)em vez de UNIQUEIDENTIFIERarmazenar Guids. Ele faz isso para tudo, incluindo chaves primárias.

Devo me preocupar?

sql-server migration
  • 2 2 respostas
  • 12523 Views

2 respostas

  • Voted
  1. Best Answer
    Solomon Rutzky
    2016-01-18T07:56:54+08:002016-01-18T07:56:54+08:00

    Devo me preocupar?

    Bem, há algumas coisas aqui que são um pouco preocupantes.

    Primeiro: embora seja verdade que a UNIQUEIDENTIFIER(ie Guid) é um valor binário de 16 bytes, também é verdade que:

    1. Todos os dados podem ser armazenados em formato binário (por exemplo , INTpodem ser armazenados em BINARY(4), DATETIMEpodem ser armazenados em BINARY(8), etc.), portanto #2 ↴
    2. Provavelmente há uma razão para ter um tipo de dados separado para GUIDs fora da mera conveniência (por exemplo sysname, como um alias para NVARCHAR(128)).

    As três diferenças comportamentais que posso encontrar são:

    • A comparação UNIQUEIDENTIFIERde valores no SQL Server, para o bem ou para o mal, não é feita da mesma forma que a comparação de BINARY(16)valores. De acordo com a página do MSDN para comparar valores GUID e uniqueidentifier , ao comparar UNIQUEIDENTIFIERvalores no SQL Server:

      os últimos seis bytes de um valor são mais significativos

    • 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 identificador único :

      a ordenação não é implementada comparando os padrões de bits dos dois valores.

    • Dado que há diferenças em como os valores GUID são tratados entre o SQL Server e o .NET (observado na página "Comparando GUID e valores de identificador exclusivo" vinculado 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 precisar emular o comportamento de comparação do SQL Server. Esse comportamento pode ser emulado convertendo-se em um SqlGuid, mas um desenvolvedor saberia fazer isso?

    Segundo: com base na seguinte declaração

    Ele faz isso para tudo, incluindo chaves primárias.

    Eu ficaria preocupado em geral com o desempenho do sistema usando GUIDs como PKs em vez de chaves alternativas junto com o uso de um INTou mesmo BIGINTcomo o PK. E ainda mais preocupado se esses GUID PKs forem os índices clusterizados.

    ATUALIZAR

    O seguinte comentário, feito pelo OP na resposta de @Rob, traz uma preocupação adicional:

    foi migrado de eu acho que MySQL

    GUIDs podem ser armazenados em 2 formatos binários diferentes . Portanto, pode haver motivo de preocupação dependendo de:

    1. em qual sistema a representação binária foi gerada e
    2. se os valores de string foram usados ​​fora do sistema original, como no código do aplicativo ou fornecidos aos clientes para uso em arquivos de importação, etc.

    O problema de onde a representação binária foi gerada tem a ver com a ordem de bytes dos primeiros 3 dos 4 "campos". Se você seguir o link acima para o artigo da Wikipedia, verá que RFC 4122 especifica o uso da codificação "Big Endian" para todos os 4 campos, mas os GUIDs da Microsoft especificam o uso de Endianness "Nativo". Bem, a arquitetura Intel é Little Endian, portanto, a ordem de bytes para os primeiros 3 campos é invertida dos sistemas que seguem o RFC (bem como GUIDs estilo Microsoft gerados em sistemas Big Endian). O primeiro campo, "Data 1", tem 4 bytes. Em um Endianness seria representado como (hipoteticamente) 0x01020304. Mas no outro Endianness seria 0x04030201. Portanto, se o banco de dados atual'BINARY(16)que a representação binária foi gerada em um sistema seguindo o RFC, a conversão dos dados atualmente no BINARY(16)campo em um UNIQUEIDENTIFIERresultará em um GUID diferente do que foi originalmente criado. Isso realmente não representa um problema SE os valores nunca saírem do banco de dados e os valores forem comparados apenas por igualdade e não por ordem.

    A preocupação com a ordenação é 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, a ordem nunca foi feita na representação binária em primeiro lugar, pois o MySQL só tem uma representação de string de UUID .

    A preocupação com os valores de string sendo usados ​​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 de bytes é potencialmente diferente, o mesmo GUID na forma de string resultaria em 2 representações binárias diferentes, dependendo de onde ocorreu a conversão. Se o código do aplicativo ou os clientes recebessem um GUID em forma de string como ABCproveniente de uma forma binária de 123 e a representação binária fosse gerada em um sistema seguindo o RFC, essa mesma representação binária (ou seja 123, ) seria convertida em uma forma de string de DEFquando convertida em a UNIQUEIDENTIFIER. Da mesma forma, a forma de string original de ABCseria convertida em uma forma binária de 456quando convertida em UNIQUEIDENTIFIER.

    Portanto, se os GUIDs nunca deixaram o banco de dados, não há muito com o que se preocupar fora do pedido. Ou, se a importação do MySQL foi feita convertendo o formato de string (ou seja FCCEC3D8-22A0-4C8A-BF35-EC18227C9F40), pode estar tudo bem. Caso contrário, 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 por meio SELECT CONVERT(UNIQUEIDENTIFIER, 'value found outside of the database');e ver se encontra o registro esperado. Se você não puder corresponder aos registros, talvez seja necessário manter os campos como BINARY(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 os novos GUIDs são inseridos? Gerado no código do app?

    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, esperamos que o seguinte seja um pouco mais claro:

    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
    

    Na saída mostrada acima, os valores "String" e "Binary" são do mesmo GUID. O valor abaixo da linha "Binary" é o mesmo valor da linha "Binary", mas formatado no mesmo estilo da linha "String" (ou seja, removeu "0x" e adicionou 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. Mas se você olhar de perto, 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 eu mostrar apenas as três primeiras seções e numerar os bytes para que seja mais fácil ver como sua ordem 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 (em Windows / SQL Server)

    Assim, dentro de cada agrupamento, a ordem dos bytes é invertida, mas apenas no Windows e também no SQL Server. No entanto, em um sistema que adere ao RFC, a representação binária espelharia a representação sting porque não haveria nenhuma reversão da ordem dos bytes.

    Como os dados foram trazidos do MySQL para o SQL Server? Aqui estão algumas opções:

    SELECT CONVERT(BINARY(16), '5FED23BE-E52C-40EE-8F45-49664C9472FD'),
           CONVERT(BINARY(16), 0x5FED23BEE52C40EE8F4549664C9472FD),
        CONVERT(BINARY(16), CONVERT(UNIQUEIDENTIFIER, '5FED23BE-E52C-40EE-8F45-49664C9472FD'));
    

    Retorna:

    0x35464544323342452D453532432D3430  
    0x5FED23BEE52C40EE8F4549664C9472FD  
    0xBE23ED5F2CE5EE408F4549664C9472FD
    

    Supondo que fosse binário direto para binário (ou seja, Converter # 2 acima), então o GUID resultante, se convertido para um real UNIQUEIDENTIFIER, seria:

    SELECT CONVERT(UNIQUEIDENTIFIER, 0x5FED23BEE52C40EE8F4549664C9472FD);
    

    Retorna:

    BE23ED5F-2CE5-EE40-8F45-49664C9472FD
    

    O que está errado. E isso nos deixa com três perguntas:

    1. Como os dados foram importados para o SQL Server?
    2. Em que idioma o código do aplicativo está escrito?
    3. Em qual plataforma o código do aplicativo está sendo executado?
    • 24
  2. Rob Farley
    2016-01-18T01:59:19+08:002016-01-18T01:59:19+08:00

    Você sempre pode se preocupar. ;)

    O sistema pode ter sido migrado de algum outro sistema que não oferece suporte ao identificador exclusivo. Existem outros compromissos que você não conhece?

    O designer pode não saber sobre o tipo de identificador único. Que outras coisas eles não sabiam?

    Tecnicamente, porém - não deve ser uma grande preocupação.

    • 5

relate perguntas

  • SQL Server - Como as páginas de dados são armazenadas ao usar um índice clusterizado

  • Preciso de índices separados para cada tipo de consulta ou um índice de várias colunas funcionará?

  • Quando devo usar uma restrição exclusiva em vez de um índice exclusivo?

  • Quais são as principais causas de deadlocks e podem ser evitadas?

  • Como determinar se um Índice é necessário ou necessário

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    conectar ao servidor PostgreSQL: FATAL: nenhuma entrada pg_hba.conf para o host

    • 12 respostas
  • Marko Smith

    Como fazer a saída do sqlplus aparecer em uma linha?

    • 3 respostas
  • Marko Smith

    Selecione qual tem data máxima ou data mais recente

    • 3 respostas
  • Marko Smith

    Como faço para listar todos os esquemas no PostgreSQL?

    • 4 respostas
  • Marko Smith

    Listar todas as colunas de uma tabela especificada

    • 5 respostas
  • Marko Smith

    Como usar o sqlplus para se conectar a um banco de dados Oracle localizado em outro host sem modificar meu próprio tnsnames.ora

    • 4 respostas
  • Marko Smith

    Como você mysqldump tabela (s) específica (s)?

    • 4 respostas
  • Marko Smith

    Listar os privilégios do banco de dados usando o psql

    • 10 respostas
  • Marko Smith

    Como inserir valores em uma tabela de uma consulta de seleção no PostgreSQL?

    • 4 respostas
  • Marko Smith

    Como faço para listar todos os bancos de dados e tabelas usando o psql?

    • 7 respostas
  • Martin Hope
    Jin conectar ao servidor PostgreSQL: FATAL: nenhuma entrada pg_hba.conf para o host 2014-12-02 02:54:58 +0800 CST
  • Martin Hope
    Stéphane Como faço para listar todos os esquemas no PostgreSQL? 2013-04-16 11:19:16 +0800 CST
  • Martin Hope
    Mike Walsh Por que o log de transações continua crescendo ou fica sem espaço? 2012-12-05 18:11:22 +0800 CST
  • Martin Hope
    Stephane Rolland Listar todas as colunas de uma tabela especificada 2012-08-14 04:44:44 +0800 CST
  • Martin Hope
    haxney O MySQL pode realizar consultas razoavelmente em bilhões de linhas? 2012-07-03 11:36:13 +0800 CST
  • Martin Hope
    qazwsx Como posso monitorar o andamento de uma importação de um arquivo .sql grande? 2012-05-03 08:54:41 +0800 CST
  • Martin Hope
    markdorison Como você mysqldump tabela (s) específica (s)? 2011-12-17 12:39:37 +0800 CST
  • Martin Hope
    Jonas Como posso cronometrar consultas SQL usando psql? 2011-06-04 02:22:54 +0800 CST
  • Martin Hope
    Jonas Como inserir valores em uma tabela de uma consulta de seleção no PostgreSQL? 2011-05-28 00:33:05 +0800 CST
  • Martin Hope
    Jonas Como faço para listar todos os bancos de dados e tabelas usando o psql? 2011-02-18 00:45:49 +0800 CST

Hot tag

sql-server mysql postgresql sql-server-2014 sql-server-2016 oracle sql-server-2008 database-design query-performance sql-server-2017

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve