Colunas de identidade ou UDF que geram explicitamente um ID exclusivo?

11

Estou no meio de um debate sobre se é melhor fazer uma PRIMARY KEYfora de um Colunas de identidade , o nosso fora de um UDF que explicitamente gera uma identificação única.

  • Estou defendendo a coluna de identidade.
  • Meu parceiro está discutindo para gerar os valores manualmente, ele afirma
    • colocando o UDF em outra tabela onde podemos ter um UDF
      • bloquear o recurso
      • incrementar uma tabela de identificação com um campo chamado ID_Valuepor1
      • use isso como um identificador exclusivo global
    • Ou peça que a tabela faça um id+1ao inserir
    • Que é mais simples mover dados entre servidores e / ou ambientes sem a restrição de identificação; movendo-se de um banco de dados em que há dados para outro banco de dados semelhante, digamos dados temporários ou simulados. Para testes em não produção, convém extrair todos os registros de ontem para a preparação para testes.

Qual implementação faz mais sentido?

kacalapy
fonte

Respostas:

21

Seu colega é um idiota.

A solução não será escalável, o UDF não é simultâneo (o mesmo motivo ). E como você lida com inserções com várias linhas: isso exigiria uma chamada UDF por linha

E a migração para outro RDBMS não acontece com frequência na vida real ... você também pode não usar o SQL Server agora e usar sequências no Oracle e torcer para não migrar.

Editar:

Sua atualização afirma que a movimentação de dados é para atualizar bancos de dados que não são de produção.

Nesse caso, você ignora as colunas de identidade ao atualizar. Você não compromete sua implementação para facilitar o carregamento sem prod. Ou use tabelas temporárias para rastrear as alterações no valor da identidade.

Ou use processos: atualizamos nosso sistema de teste todas as noites da produção, o que evita completamente o problema. (E garante que nosso backup do produto também possa ser restaurado)

gbn
fonte
11

Use um valor de identidade. A geração de sua própria tabela e valores de sequência exigirá muita sobrecarga e causará muitos bloqueios e bloqueios ao tentar gerar números.

A identidade existe por uma razão, use-a.

Quando o SQL Denali for lançado, ele oferecerá suporte a seqüências que serão mais eficientes que a identidade, mas você não poderá criar algo mais eficiente.

Quanto à movimentação de registros de um ambiente para outro, ative IDENTITY_INSERT ao fazer a inserção ou marque a caixa no SSIS.

mrdenny
fonte
Se você passar de "produção" para "teste" e tiver um campo de identidade, corre o risco de sobrescrever ou colidir com dados. É tudo o que estou dizendo. Sim, não deve ser um problema nessa direção, mas só estou dizendo que isso pode acontecer.
jcolebrand
É verdade que você terá o mesmo número para diferentes valores de linha em dev, test, qa, uat e produção. E daí? Se esses valores forem importantes (como para uma tabela de pesquisa), codifique-os manualmente, o que não deve ser um problema, pois você não deve colocar valores nessas tabelas com muita frequência. Se você precisar controlar os valores de identidade entre os ambientes para evitar colisões, redefina os valores de identidade entre os ambientes quando restaurar da produção.
mrdenny
5

A coluna de identidade soa bem para mim. Não sei se sigo a lógica sobre por que é difícil mover dados entre servidores.

Se você deseja que cada linha tenha uma identidade globalmente exclusiva, você pode usar um UUID, mas eu não faria isso, a menos que você tenha certeza de que a exclusividade global é necessária - geralmente não é. O uso de UUIDs como IDs diminuirá o desempenho, aumentará os requisitos de espaço em disco e tornará a depuração mais difícil - devido ao tamanho, é difícil lembrar de um UUID, contá-lo a alguém por telefone ou anotá-lo no papel sem erros.

Mark Byers
fonte
4

Para IDs numéricos simples, basta ir com a identidade e esquecer todos os problemas de gerá-los manualmente.

Você sempre pode criar uma "super tabela" que use uma identidade como PK e tenha uma coluna de tipo e qualquer outra informação. Quando você precisar de um novo ID (supondo que você queira dizer IDS exclusivo em tabelas diferentes), insira nesta tabela e agarre SCOPE_IDENTITY()ae, em seguida, insira na tabela real de que você precisa.

Basicamente, você cria uma tabela: MasterIDs com uma identidade PK, quando você precisar inserir uma linha em sua Tabela1, INSERT INTO MasterIDse obter a identidade gerada por essa linha usando SCOPE_IDENTITY()e depois inserir na Tabela1 usando esse valor como PK.

A Tabela1 terá uma PK int sem identidade. Você faria o mesmo processo para inserir na Tabela2, etc. Deixe o SQL Server gerenciar os valores de identidade na tabela MasterIDs , que você poderá usar nas outras tabelas. Os MasterIDs podem conter outras tabelas, como o tipo (para que você saiba qual tabela, Tabela1 ou Tabela2, etc, usa esse valor de identidade.

Paul White 9
fonte
3

Contanto que você esteja usando as restrições de chave estrangeira corretamente (em cascata, atualizando etc.), você poderá usar um campo de identidade. Realmente não vejo vantagem para a outra solução neste caso.

Joe Phillips
fonte
2

A identidade foi criada para se ajustar ao seu cenário. Você tem ferramentas como replicação para troca de dados de servidor / ambiente que mantêm tudo junto.


fonte
1

Acabei de concluir uma parte do trabalho em que substituí uma identitycoluna do SQL Server por um intcampo normal e eu mesma alocação de ID controlada.

Vi ganhos de desempenho bastante impressionantes. Ao contrário do OP, não tenho um UDF para gerar o ID. Mas o princípio é praticamente o mesmo: existe parte do software que mantém um pool de IDs. Quando eles acabam, ele recebe outro lote consultando o banco de dados para o próximo valor baixo e o incrementa para o próximo alto .

Isso nos permite gerar IDs e relacionar todas as entidades fora de uma transação em nosso ORM antes de enviarmos os lotes ao banco de dados e também enviar lotes maiores sem ida e volta para obter a identidade inserida (exigida pelas colunas de identidade).

Na tabela de identificação que temos, há mais de uma linha, permitindo usar intervalos específicos, se assim o desejarmos. ou seja, para reutilizar blocos excluídos e IDs negativos.

Marca
fonte
0

Uso identidade há anos e considero seriamente substituir o número de identidade por UNIQUEIDENTIFIER. É um pesadelo quando você precisa alterar o tipo de dados, se alguém o projetou para ser um banco de dados compacto e um pesadelo, se você precisar adicionar identidade a uma coluna, também não será possível atualizar a coluna de identidade. Imagine que você coloca um int e seu banco de dados cresce além de 2 bilhões de registros, novamente um pesadelo para mudar (considere FKs)! Mudar qualquer coisa com identidade é um pesadelo e não é favorável à escala, a menos que você coloque o bigint! UNIQUEIDENTIFIER vs Identity = conveniência e robustez vs talvez melhoria notável de desempenho (não fez o benchmark).

Atualização: Depois de ver isso , definitivamente me inclino para o UNIQUEIDENTIFIER. Isso não mostra nenhum benefício real da identidade bigint e muitos benefícios para o UNIQUEIDENTIFIER! Versões diferentes do SQL Server podem ter um resultado diferente. Há uma beleza em ter um ID único em todos os bancos de dados e sistemas (robustez)! Mova, copie, transforme dados como quiser! https://www.mssqltips.com/sqlservertip/5105/sql-server-performance-comparison-int-versus-guid/

Hrvoje Batrnek
fonte
A INT 64 bits vai durar um longo tempo ...
Verace