Sei que esse tipo de pergunta surge muito, mas ainda não li nenhum argumento convincente para me ajudar a tomar essa decisão. Por favor, tenha paciência comigo!
Eu tenho um banco de dados enorme - ele cresce cerca de 10.000.000 de registros por dia. Os dados são relacionais e, por motivos de desempenho, carrego a tabela com BULK COPY. Por esse motivo, preciso gerar chaves para as linhas e não posso contar com uma coluna IDENTITY.
Um inteiro de 64 bits - um bigint - é grande o suficiente para eu usar, mas para garantir a exclusividade, preciso de um gerador centralizado para criar meus IDs para mim. Atualmente, tenho um serviço de gerador que permite que um serviço reserve X números de sequência e garanta a ausência de colisões. No entanto, uma consequência disso é que todos os serviços que tenho dependem desse gerador centralizado e, portanto, estou limitado em como posso distribuir meu sistema e não estou satisfeito com as outras dependências (como exigir acesso à rede) impostas por este projeto. Isso tem sido um problema na ocasião.
Agora estou pensando em usar GUIDs sequenciais como minhas chaves primárias (geradas externamente para SQL). Pelo que pude verificar em meus próprios testes, a única desvantagem disso é a sobrecarga de espaço em disco de um tipo de dados mais amplo (que é exacerbado por seu uso em índices). Não testemunhei nenhuma desaceleração perceptível no desempenho da consulta, em comparação com a alternativa bigint. Carregar a tabela com BULK COPY é um pouco mais lento, mas não muito. Meus índices baseados em GUID não estão se tornando fragmentados graças à minha implementação de GUID sequencial.
Basicamente, o que eu quero saber é se há alguma outra consideração que eu possa ter esquecido. No momento, estou inclinado a dar o salto e começar a usar GUIDs. Eu não sou um especialista em banco de dados, então eu realmente aprecio qualquer orientação.
Estou em uma mesma situação semelhante. Atualmente, estou usando a abordagem GUID sequencial e não tenho fragmentação e geração de chave fácil.
Percebi duas desvantagens que me levaram a começar a migrar para o bigint:
(2) Foi o assassino para mim.
Agora vou gerar minhas chaves assim:
Estarei usando uma data inicial mais hora e tendo uma parte sequencial depois disso. Isso me permite consultar meus dados por intervalo sem nenhum índice de adição. Este é um bom bônus para mim.
Vou gerar a parte sequencial do bigint usando um algoritmo HiLo que se presta bem a ser distribuído .
Espero que algumas dessas transferências para a sua situação. Eu definitivamente recomendo usar bigint.
Com um tipo
INT
, começando em 1, você obtém mais de 2 bilhões de linhas possíveis - isso deve ser mais do que suficiente para a grande maioria dos casos. ComBIGINT
, você obtém aproximadamente 922 quatrilhões (922 com 15 zeros - 922.000 bilhões) - o suficiente para você?Se você usar um
INT IDENTITY
início em 1 e inserir uma linha a cada segundo, precisará de 66,5 anos antes de atingir o limite de 2 bilhões....Se você usar um
BIGINT IDENTITY
início em 1 e inserir mil linhas a cada segundo, precisará de impressionantes 292 milhões de anos antes de atingir o limite de 922 quatrilhões....Usando seus 10 milhões de linhas por dia, você terá números suficientes para aproximadamente 1'844'674'407'370 dias ( 1844 bilhões de dias ou um tique acima de 5 bilhões de anos ) de dados - isso é bom o suficiente para suas necessidades ?
Leia mais sobre isso (com todas as opções disponíveis) nos MSDN Books Online .
Eu recomendo que você use SEQUENCE do tipo de dados BIGINT no SQL 2012 Isso é muito mais flexível do que IDENTITY com opções como cache/nocache, você também pode atribuir um intervalo de sequência para sua operação em lote como sp_sequence_get_range.
A razão pela qual você não pode usar IDENTITY é porque já existem relacionamentos de chave estrangeira entre tabelas separadas que você está carregando? E não há outra chave natural para você conseguir conectá-los em uma operação de uma área de preparação para a área de produção? Por esse motivo, gostaria de saber um pouco mais sobre como eles estão "vinculados" no sistema de origem antes de você copiar em massa? Os sistemas de origem múltipla simplesmente usam suas próprias sequências e têm a possibilidade de sequências conflitantes quando colocadas em um banco de dados compartilhado?
A técnica COMB ID/GUID sequencial é aquela com a qual estou familiarizado e é viável sempre que você precisar efetivamente dessa exclusividade global atribuída fora do banco de dados - é efetivamente uma identidade de linha utilizável dentro e fora do banco de dados. Por esse motivo, em ambientes altamente distribuídos ou cenários desconectados, é uma boa escolha
Exceto se você realmente não precisar, porque essa diferença de largura extra é significativa quando o tamanho dos dados aumenta e essas chaves estão em todos os índices e os conjuntos de trabalho para muitas consultas.
Além disso, com a geração distribuída, se as linhas não vierem realmente na ordem da coluna GUID, os problemas com o uso disso para a chave de índice clusterizado (estreito, estático, crescente) podem causar alguma fragmentação em comparação com o clustering em uma IDENTITY ainda permanecer.
Em geral é possível usar a
OUTPUT
cláusula deINSERT
comando para que os dados sejam inseridos em ambas as tabelas e relacionados com o campo de identidade.O identificador baseado no registro de data e hora não deve ser considerado confiável - depende do relógio do sistema, que por sua vez depende de muitas coisas - do relógio do hardware aos serviços de sincronização de tempo.