Qual é a melhor prática para chaves primárias em tabelas?

256

Ao projetar tabelas, desenvolvi o hábito de ter uma coluna única e que eu crio a chave primária. Isso é alcançado de três maneiras, dependendo dos requisitos:

  1. Coluna de número inteiro de identidade que é incrementada automaticamente.
  2. Identificador exclusivo (GUID)
  3. Uma coluna de caracteres curtos (x) ou número inteiro (ou outro tipo numérico relativamente pequeno) que pode servir como uma coluna identificadora de linha

O número 3 seria usado para pesquisas bastante pequenas, principalmente tabelas de leitura que podem ter um código estático exclusivo de cadeia de comprimento ou um valor numérico, como um ano ou outro número.

Na maioria das vezes, todas as outras tabelas terão um número inteiro com auto incremento ou chave primária de identificador exclusivo.

A questão :-)

Recentemente, comecei a trabalhar com bancos de dados que não possuem identificador de linha consistente e as chaves primárias estão atualmente agrupadas em várias colunas. Alguns exemplos:

  • data / hora / caractere
  • datetime / inteiro
  • datetime / varchar
  • char / nvarchar / nvarchar

Existe um caso válido para isso? Eu sempre teria definido uma coluna de identidade ou identificador exclusivo para esses casos.

Além disso, existem muitas tabelas sem chaves primárias. Quais são os motivos válidos, se houver, para isso?

Estou tentando entender por que as tabelas foram projetadas como eram e me parece uma grande bagunça, mas talvez houvesse boas razões para isso.

Uma terceira pergunta para me ajudar a decifrar as respostas: nos casos em que várias colunas são usadas para compor a chave primária composta, existe uma vantagem específica para esse método versus uma chave substituta / artificial? Estou pensando principalmente em desempenho, manutenção, administração, etc.?

Lloyd Cotten
fonte
Eu achei uma boa leitura das habilidades de banco de dados: uma abordagem saudável para a escolha de chaves primárias e sigo a maioria dos pontos descritos.
usar o seguinte comando

Respostas:

254

Sigo algumas regras:

  1. As chaves primárias devem ser tão pequenas quanto necessárias. Prefira um tipo numérico porque os tipos numéricos são armazenados em um formato muito mais compacto do que os formatos de caracteres. Isso ocorre porque a maioria das chaves primárias serão chaves estrangeiras em outra tabela e usadas em vários índices. Quanto menor sua chave, menor o índice, menos páginas no cache você usará.
  2. As chaves primárias nunca devem mudar. A atualização de uma chave primária deve estar sempre fora de questão. Isso ocorre porque é mais provável que seja usado em vários índices e usado como uma chave estrangeira. A atualização de uma única chave primária pode causar o efeito cascata das alterações.
  3. NÃO use "chave primária do seu problema" como chave primária do modelo lógico. Por exemplo, número do passaporte, número da previdência social ou número do contrato do funcionário, pois essas "chaves primárias" podem mudar para situações do mundo real.

Em substituto vs chave natural, refiro-me às regras acima. Se a chave natural for pequena e nunca for alterada, poderá ser usada como chave primária. Se a chave natural for grande ou provável que eu mude, uso chaves substitutas. Se não houver chave primária, eu ainda faço uma chave substituta porque a experiência mostra que você sempre adiciona tabelas ao seu esquema e deseja que você coloque uma chave primária no lugar.

Logicalmind
fonte
3
Eu gosto disso! Você tem alguma documentação para a base de suas "regras"? Obrigado!
Lloyd Cotten
4
Não, apenas experiência. Ao lidar com bancos de dados "pequenos", essas coisas não importam muito. Mas quando você lida com grandes bancos de dados, todas as pequenas coisas são importantes. Imagine se você tiver 1 bilhão de linhas com pacotes int ou longos em comparação com o uso de texto ou guias. Há uma enorme diferença!
Logicalmind 3/08/08
44
Lembre-se de colocar esse índice exclusivo na chave natural (se realmente existir, o que geralmente não é o caso) quando você usar uma chave artificial.
HLGEM 9/08/08
3
@Loyd Cotten: Eis o que um provedor de mecanismos de big data diz em apoio à regra número 1: skyfoundry.com/forum/topic/24 . Isso me convenceu a voltar para Ints
hobs
4
mesmo se você "souber" que "a chave natural é pequena e nunca mudará", pense duas vezes. "nunca reutilizamos esses códigos" são as últimas palavras famosas ... Sobre as únicas coisas que se enquadram nas categorias de pequeno, nunca mudando, são iso e outros padrões (códigos de país, códigos de aeroportos IATA). Coisas como "qual é a representação de duas letras para essa marca interna" ... pense duas vezes antes de assumir que "isso" nunca mudará, você é uma decisão financeira longe de uma reconstrução de banco de dados.
Andrew Hill
90

Versos naturais chaves artificiais é um tipo de debate religioso entre a comunidade de bancos de dados - veja este artigo e outros com os quais ele vincula. Não sou a favor de sempre ter chaves artificiais, nem de nunca tê-las. Eu decidiria caso a caso, por exemplo:

  • Estados dos EUA: eu usaria o state_code ('TX' no Texas etc.), em vez de state_id = 1 no Texas
  • Funcionários: eu normalmente criaria um employee_id artificial, porque é difícil encontrar qualquer outra coisa que funcione. O SSN ou equivalente pode funcionar, mas pode haver problemas como um novo marceneiro que ainda não forneceu o SSN.
  • Histórico de salários dos funcionários: (employee_id, start_date). Eu não criaria um funcionário artificial_salary_history_id. A que ponto isso serviria (além de "consistência tola" )

Onde quer que chaves artificiais sejam usadas, você também deve sempre declarar restrições exclusivas nas chaves naturais. Por exemplo, use state_id, se necessário, mas é melhor declarar uma restrição exclusiva em state_code; caso contrário, você certamente terá:

state_id    state_code   state_name
137         TX           Texas
...         ...          ...
249         TX           Texas
Tony Andrews
fonte
9
Em alguns casos, com o SQL Server 2005/2008, a chave natural (texto) pode ser mais rápida que uma chave int. Eu tenho um aplicativo com um código amigável de 7-8 caracteres que usamos como chave primária e que foi mais rápido (e geralmente mais conveniente) do que um substituto int. De qualquer maneira, precisávamos do código para que pudéssemos ter um código legível / memorável humano que pudéssemos transferir com segurança sem conflito para uma instância de aplicativo diferente (vários sites que se agregam em um site maior).
lambacck 30/05
1
+1 boa resposta. No entanto, eu gostaria que o oficial de pessoal fosse a fonte confiável de um identificador de funcionário, ou seja, o oficial responsável por verificar na vida real os funcionários que provavelmente usem identificadores como SSN, busque referências etc. O departamento de pessoal deve ser confiável fonte de identificadores de funcionários, não o DBMS!
precisa saber é o seguinte
@ onedaywhen- eu não. confie no oficial de pessoal. As pessoas vão embora, novas vêm e têm idéias diferentes. Proporcionar-lhes acesso ao identificador eles acham que é exclusivo / eles querem usar, mas internamente para o db, dba deve fazer a sua própria decisão
Dave Pilha
1
Observe que o SSN não é necessariamente único em todos os países. Pelo menos na Áustria, várias pessoas podem compartilhar o mesmo número
maja
Também em alguns países (acho que mesmo nos EUA) eles realmente recomendam não compartilhar o SSN.
Stijn de Witt
25

Apenas um comentário extra sobre algo que geralmente é esquecido. Às vezes, não usar uma chave substituta traz benefícios nas tabelas filho. Digamos que tenhamos um design que permita executar várias empresas no mesmo banco de dados (talvez seja uma solução hospedada ou o que for).

Digamos que temos essas tabelas e colunas:

Company:
  CompanyId   (primary key)

CostCenter:
  CompanyId   (primary key, foreign key to Company)
  CostCentre  (primary key)

CostElement
  CompanyId   (primary key, foreign key to Company)
  CostElement (primary key)

Invoice:
  InvoiceId    (primary key)
  CompanyId    (primary key, in foreign key to CostCentre, in foreign key to CostElement)
  CostCentre   (in foreign key to CostCentre)
  CostElement  (in foreign key to CostElement)

Caso esse último bit não faça sentido, faça Invoice.CompanyIdparte de duas chaves estrangeiras, uma na tabela CostCentre e outra na tabela CostElement . A chave primária é ( InvoiceId , CompanyId ).

Nesse modelo, não é possível errar e referenciar um CostElement de uma empresa e um CostCentre de outra empresa. Se uma chave substituta foi usada nos CostElement e mesas CostCentre , que seria.

Quanto menos chances de estragar, melhor.

WW.
fonte
6
Essa é uma desvantagem sub-citada ao usar chaves substitutas. Se a tabela tiver uma chave substituta, ainda posso usá-la para esses tipos de restrições. Infelizmente, embora a restrição exija um índice e seja estranho criar um índice exclusivo em (surrogate_key, other_column) quando (surrogate_key) for único por si só. Além disso, (other_column) costuma ser totalmente redundante em uma tabela de mapas, já que (surrogate_key) é única na estrangeira. Barrigas de aluguel podem realmente estragar as coisas.
Samuel Danielson
24

Evito usar chaves naturais por uma simples razão - erro humano. Embora frequentemente estejam disponíveis identificadores exclusivos naturais (SSN, VIN, número da conta etc.), eles exigem que um ser humano os insira corretamente. Se você estiver usando SSNs como chave primária, alguém transporá alguns números durante a entrada de dados e o erro não será descoberto imediatamente, você terá que alterar sua chave primária.

Minhas chaves primárias são todas tratadas pelo programa de banco de dados em segundo plano e o usuário nunca as conhece.

Paulo
fonte
1
Trabalhei com alguns bancos de dados que usavam SSNs ou IDs de imposto como chaves primárias. Ineficiente quando se trata de referências de armazenamento e chave estrangeira. Sem mencionar que o SSN de uma pessoa pode mudar. Então, eu concordo completamente com você.
21813 Alex Jorgenson
13

Não há problema em criar sua chave primária a partir de vários campos, é uma chave natural .

Você pode usar uma coluna Identidade (associada a um índice exclusivo nos campos candidatos) para criar uma Chave de Substituição .

Essa é uma discussão antiga. Prefiro chaves substitutas na maioria das situações.

Mas não há desculpa para a falta de uma chave.

RE: EDIT

Sim, há muita controvérsia sobre isso: D

Não vejo nenhuma vantagem óbvia nas chaves naturais, além do fato de serem a escolha natural. Você sempre pensará em Nome, Número Social - ou algo assim - em vez de idPerson .

Chaves substitutas são a resposta para alguns dos problemas que as chaves naturais têm (propagando alterações, por exemplo).

À medida que você se acostuma a substitutos, parece mais limpo e gerenciável.

Mas no final, você descobrirá que é apenas uma questão de gosto - ou mentalidade -. As pessoas "pensam melhor" com chaves naturais e outras não.

DonOctavioDelFlores
fonte
13
As pessoas "pensam melhor" com chaves naturais. Máquinas e bancos de dados, não.
FDCastel
11

As tabelas devem ter uma chave primária o tempo todo. Quando isso não acontecer, deveria ter sido um campo de AutoIncremento.

Às vezes, as pessoas omitem a chave primária porque transferem muitos dados e isso pode retardar (dependendo do banco de dados) o processo. MAS, deve ser adicionado depois.

Algum comentário sobre a tabela de links , isso é correto, é uma exceção, mas os campos devem ser FK para manter a integridade e, em alguns casos, esses campos também podem ser chaves primárias se a duplicação de links não for autorizada ... forma simples, porque a exceção é algo frequentemente na programação, a chave primária deve estar presente para manter a integridade dos seus dados.

Patrick Desjardins
fonte
Concordo. E no caso em que um monte de dados é para ser inserido, remova a restrição de chave primária (ou use inserção de identidade ON em TSQL) e colocá-lo de volta depois :)
Andrew Rollings
1
Há exceções: tabelas de ligação, obviamente
annakata
Outro motivo: se não houver chave PK / exclusiva, os navegadores de tabela (quero dizer, algo como o Access / SQL Server Management Studio) se recusarão a atualizar / excluir uma única linha com linha duplicada. Você terá que escrever SQL para isso.
Dennis C
É bastante comum omitir uma PK de uma tabela de fatos do armazém de dados. No Oracle você pode fazer referência a pseudocoluna ROWID como um identificador exclusivo no curto prazo (ou seja, não armazená-lo em algum lugar e esperar que ele não a mudança.)
David Aldridge
9

Além de todas essas boas respostas, só quero compartilhar um bom artigo que acabei de ler: O grande debate sobre chaves primárias .

Apenas para citar alguns pontos:

O desenvolvedor deve aplicar algumas regras ao escolher uma chave primária para cada tabela:

  • A chave primária deve identificar exclusivamente cada registro.
  • O valor da chave primária de um registro não pode ser nulo.
  • O valor-chave principal deve existir quando o registro é criado.
  • A chave primária deve permanecer estável - você não pode alterar o (s) campo (s) de chave primária.
  • A chave primária deve ser compacta e conter o menor número possível de atributos.
  • O valor da chave primária não pode ser alterado.

Chaves naturais (tendem a) violam as regras. Chaves substitutas cumprem as regras. (É melhor você ler esse artigo, vale a pena!)

RayLuo
fonte
7

O que há de especial na chave primária?

Qual é o objetivo de uma tabela em um esquema? Qual é o propósito de uma chave de uma tabela? O que há de especial na chave primária? As discussões em torno das chaves primárias parecem não entender o ponto em que a chave primária faz parte de uma tabela e essa tabela faz parte de um esquema. O que é melhor para a tabela e os relacionamentos da tabela deve orientar a chave usada.

As tabelas (e os relacionamentos das tabelas) contêm fatos sobre as informações que você deseja registrar. Esses fatos devem ser independentes, significativos, facilmente compreendidos e não contraditórios. Da perspectiva do design, outras tabelas adicionadas ou removidas de um esquema não devem impactar a tabela em questão. Deve haver um objetivo de armazenar os dados relacionados apenas às informações em si. Entender o que é armazenado em uma tabela não deve exigir a realização de um projeto de pesquisa científica. Nenhum fato armazenado para a mesma finalidade deve ser armazenado mais de uma vez. As chaves são uma parte ou parte das informações que estão sendo registradas, únicas, e a chave primária é a chave especialmente designada que deve ser o ponto de acesso principal da tabela (ou seja, deve ser escolhida para consistência e uso dos dados, não apenas inserir desempenho).

  • LADO Lateral: Infelizmente, o efeito colateral da maioria dos bancos de dados sendo projetados e desenvolvidos por programadores de aplicativos (o que eu sou algumas vezes) é que o melhor para o aplicativo ou a estrutura do aplicativo geralmente direciona a opção de chave primária para as tabelas. Isso leva a chaves inteiras e GUID (como essas são simples de usar para estruturas de aplicativos) e a designs de tabelas monolíticas (pois reduzem o número de objetos da estrutura de aplicativos necessários para representar os dados na memória). Essas decisões de design de banco de dados orientadas a aplicativos levam a problemas significativos de consistência de dados quando usados ​​em escala. As estruturas de aplicativos projetadas dessa maneira naturalmente levam a projetos de tabela por vez. "Registros parciais" são criados em tabelas e dados preenchidos ao longo do tempo. A interação de várias tabelas é evitada ou quando usada causa dados inconsistentes quando o aplicativo funciona incorretamente. Esses designs levam a dados que não têm sentido (ou são difíceis de entender), espalham-se por tabelas (é necessário examinar outras tabelas para entender a tabela atual) e duplicar os dados.

Dizia-se que as chaves primárias deveriam ser tão pequenas quanto necessárias. Eu diria que as chaves devem ter apenas o tamanho necessário. A adição aleatória de campos sem sentido a uma tabela deve ser evitada. É ainda pior criar uma chave de um campo sem sentido adicionado aleatoriamente, especialmente quando ela destrói a dependência de junção de outra tabela na chave não primária. Isso é razoável apenas se não houver boas chaves candidatas na tabela, mas essa ocorrência certamente é um sinal de um design de esquema ruim se usado para todas as tabelas.

Também foi dito que as chaves primárias nunca deveriam mudar, pois a atualização de uma chave primária sempre deveria estar fora de questão. Mas atualização é o mesmo que excluir, seguido de inserção. Por essa lógica, você nunca deve excluir um registro de uma tabela com uma chave e adicionar outro registro com uma segunda chave. Adicionar a chave primária substituta não remove o fato de que a outra chave na tabela existe. A atualização de uma chave não primária de uma tabela pode destruir o significado dos dados se outras tabelas dependem desse significado por meio de uma chave substituta (por exemplo, uma tabela de status com uma chave substituta cuja descrição do status foi alterada de 'Processado' para 'Cancelado definitivamente corromperia os dados). O que sempre deve estar fora de questão é destruir o significado dos dados.

Dito isso, sou grato pelos muitos bancos de dados mal projetados que existem hoje nas empresas (gigantes sem sentido-substitutos-com-dados-corrompidos-1NF), porque isso significa que há uma quantidade infinita de trabalho para pessoas que entendem o design adequado do banco de dados . Mas, no lado triste, às vezes me faz sentir como Sísifo, mas aposto que ele tinha um total de 401k (antes do acidente). Fique longe de blogs e sites para perguntas importantes sobre o design do banco de dados. Se você estiver projetando bancos de dados, procure Data CJ. Você também pode fazer referência ao Celko para SQL Server, mas apenas se segurar o nariz primeiro. No lado do Oracle, consulte Tom Kyte.

Lucas
fonte
1
"Por essa lógica, você nunca deve excluir um registro de uma tabela com uma chave e adicionar outro registro com uma segunda chave." - Há um caso para isso, e é efetivamente o que uma cláusula "ON DELETE RESTRICT" em uma chave estrangeira fará. Em alguns casos (digamos onde é necessária uma trilha de auditoria), um campo booleano "excluído" seria melhor do que permitir que o registro seja excluído.
Waz
6

Uma chave natural, se disponível, geralmente é a melhor. Portanto, se datetime / char identifica exclusivamente a linha e as duas partes são significativas para a linha, isso é ótimo.

Se apenas a data e o horário forem significativos e o caractere for adornado para torná-lo único, você pode também optar por um campo de identificação.

James Curran
fonte
9
Geralmente melhor? Não tenho base científica, mas tenho quase certeza de que a maioria das pessoas prefere uma chave substituta ao natural. Em muitos casos, não há chave natural.
JC.
3
SEMPRE deve haver uma chave natural para qualquer linha do seu banco de dados. Essa chave "natural" pode ser algo gerado no mundo dos negócios ou pelo seu sistema técnico, mas sempre deve existir.
Tom H
2
Se, no seu mundo, isso foi determinado como a única maneira de identificar uma linha na tabela, então sim. Obviamente, quando um designer decide criar um GUID para uma PK, geralmente é porque não fez o trabalho para encontrar a chave natural REAL, portanto, nesse caso, o GUID NÃO é a chave natural.
Tom H
8
2. Se você pegar sua chave do mundo natural, o mundo natural mudará para quebrar sua chave. Se você usar o número de telefone, receberá dois usuários da mesma casa. Se você usar o sobrenome, eles se casam. Se você usar o SSN, as leis de privacidade serão alteradas e exigirão a sua remoção.
James Orr
2
@ Barry: RE: # 2. se o mundo natural mudar e isso fizer com que sua chave natural mude, isso significa que você fez um mau trabalho ao selecionar uma chave natural. Por definição, uma chave natural não muda com o tempo.
Tom H
6

Aqui está minha regra de ouro em que me decidi após mais de 25 anos de experiência em desenvolvimento.

  • Todas as tabelas devem ter uma chave primária de coluna única que é incrementada automaticamente.
  • Inclua-o em qualquer visualização que possa ser atualizável
  • A chave primária não deve ter nenhum significado no contexto do seu aplicativo. Isso significa que não deve ser um SKU, nem um número de conta ou um ID de funcionário ou qualquer outra informação significativa para o seu aplicativo. É apenas uma chave exclusiva associada a uma entidade.

A chave primária é usada pelo banco de dados para fins de otimização e não deve ser usada pelo seu aplicativo para nada além de identificar uma entidade específica ou relacionada a uma entidade específica.

Sempre ter uma chave primária de valor único torna a execução de UPSERTs muito simples.

Use índices adicionais para suportar chaves com várias colunas que tenham significado no seu aplicativo.

Rodney P. Barbati
fonte
5

Chaves naturais versus chaves artificiais para mim são uma questão de quanto da lógica de negócios você deseja em seu banco de dados. O número do Seguro Social (SSN) é um ótimo exemplo.

"Cada cliente no meu banco de dados terá e deve ter um SSN." Bam, pronto, faça dela a chave primária e pronto. Lembre-se de quando as regras da sua empresa mudam, você está queimado.

Eu não gosto de chaves naturais, devido à minha experiência em alterar as regras de negócios. Mas se você tem certeza de que não vai mudar, isso pode impedir algumas associações críticas.

Dan Williams
fonte
8
E vi dados em que o SSN não é único, mesmo que devesse ser. Desconfie de chaves naturais se importar seus dados de outra fonte!
HLGEM
2
Se você está sujeito a roubo de identidade, pode alterar seu número de segurança social. Existem mais quatro situações em que eles alteram seu número e estão listados no site ssa.gov.
Zvi Twersky
4

Suspeito que a terapia de jornal enrolada de Steven A. Lowe seja necessária para o designer da estrutura de dados original.

Como um aparte, os GUIDs como chave primária podem ser prejudiciais ao desempenho. Eu não recomendaria.

Andrew Rollings
fonte
2
Dizer que é um porco de desempenho é uma otimização prematura. Guias são necessários em alguns casos (clientes desconectados, mesclagem futura de tabelas, replicação)
JC.
2
"Otimização prematura" é uma frase usada em excesso no SO (IMHO)! Sim, os GUIDs podem ser necessários em ALGUNS casos, mas Andrew tem razão em apontar que eles não devem ser usados ​​como o tipo de dados padrão, seja necessário ou não.
Tony Andrews
OK, não foi realmente uma otimização prematura. O que eu quis dizer é que a maioria das pessoas não experimenta o volume necessário para perceber a diferença de desempenho. Sim, use o incremento automático se souber que nunca precisará de um guia.
JC.
Ou use ambos. Tenha uma chave primária baseada em int / long para boas seleções e junções rápidas e, em seguida, tenha um campo de guia. Pelo menos, é o que estou fazendo. Isso está errado? Eu não deveria estar fazendo isso? :)
Andrew Rollings
Eu também estou usando as duas colunas. Mas não tenho certeza se está errado ou não. Você encontrou @AndrewRollings?
YÒGÎ 22/03
3

Você deve usar uma chave primária 'composta' ou 'composta' que compreende vários campos.

Esta é uma solução perfeitamente aceitável, clique aqui para obter mais informações :)

Adão
fonte
3

Eu também sempre uso uma coluna de ID numérica. No oracle, eu uso o número (18,0) sem motivo real acima do número (12,0) (ou seja, um int e não um longo), talvez eu não queira me preocupar em obter alguns bilhões de linhas em o db!

Também incluo uma coluna criada e modificada (tipo timestamp) para rastreamento básico, onde parece útil.

Não me importo de definir restrições exclusivas em outras combinações de colunas, mas gosto muito do meu id, criado, modificado pelos requisitos da linha de base.

JeeBee
fonte
2
Devo também salientar que não coloco IDs em tabelas de vínculo / junção, apenas nas tabelas que contêm dados.
21468 JeeBee
3

Eu procuro chaves primárias naturais e as uso sempre que posso.

Se nenhuma chave natural puder ser encontrada, prefiro um GUID a um INT ++ porque o SQL Server usa árvores e é ruim sempre adicionar chaves ao final nas árvores.

Nas tabelas que são acoplamentos muitos para muitos, uso uma chave primária composta das chaves estrangeiras.

Como tenho a sorte de usar o SQL Server, posso estudar os planos e estatísticas de execução com o criador de perfil e o analisador de consultas e descobrir como minhas chaves estão executando com muita facilidade.

Guge
fonte
Você tem alguma documentação para fazer backup desta declaração: 'se nenhuma chave natural puder ser encontrada, prefiro um GUID a um INT ++ porque o SQL Server usa árvores e é ruim sempre adicionar chaves ao final nas árvores.' Não é cético, apenas tentando compilar alguma documentação.
Lloyd Cotten
1
@Loyd - Que bom que você está se interessando por algo que eu acho muito fascinante. Um bom ponto de partida em msdn.microsoft.com/en-us/library/ms177443(SQL.90).aspx
Guge
2

Eu sempre uso um número automático ou um campo de identidade.

Eu trabalhei para um cliente que usava o SSN como chave primária e, por causa dos regulamentos da HIPAA, fui forçado a mudar para um "MemberID" e isso causou muitos problemas ao atualizar as chaves estrangeiras nas tabelas relacionadas. Manter um padrão consistente de uma coluna de identidade me ajudou a evitar um problema semelhante em todos os meus projetos.

Matt
fonte
6
A má seleção de uma chave natural por um desenvolvedor não significa que as chaves naturais são ruins.
Tom H
1
Uma ferramenta difícil de usar de alguma forma não é um ponto contra essa ferramenta?
Sqeaky
1

Todas as tabelas devem ter uma chave primária. Caso contrário, o que você tem é um HEAP - isso, em algumas situações, pode ser o que você deseja (carga pesada de inserção quando os dados são replicados por meio de um broker de serviço para outro banco de dados ou tabela, por exemplo).

Para tabelas de pesquisa com um baixo volume de linhas, você pode usar um código 3 CHAR como chave primária, pois isso ocupa menos espaço que um INT, mas a diferença de desempenho é insignificante. Fora isso, eu sempre usaria uma INT, a menos que você tenha uma tabela de referência que talvez tenha uma chave primária composta composta de chaves estrangeiras de tabelas associadas.

Coolcoder
fonte
1

Se você realmente quiser ler todas as idas e vindas deste debate antigo, faça uma pesquisa por "chave natural" no Stack Overflow. Você deve receber páginas de resultados.

Tom H
fonte
1

Os GUIDs podem ser usados ​​como uma chave primária, mas você precisa criar o tipo certo de GUID para que ele funcione bem.

Você precisa gerar GUIDs COMB. Um bom artigo sobre isso e as estatísticas de desempenho são O custo dos GUIDs como chaves primárias .

Também algum código na criação de GUIDs COMB no SQL está em Uniqueidentifier vs identity ( archive ) .

Donny V.
fonte
5
IMHO, os guias só devem ser usados ​​quando você precisar sincronizar dados entre os bancos de dados. No qual um ID gerado automaticamente é problemático. A diferença entre usar um guid e usar um tipo numérico básico é que um guid precisará de 16 bytes por linha, enquanto um numérico será muito menor.
Logicalmind 3/08/08
Se você acessar o link que forneci acima, há muito pouca diferença no desempenho usando os Guias COMB.
Donny V.
0

Fazemos muitas junções e as chaves primárias compostas acabaram de se tornar um problema de desempenho. Um simples int ou long resolve muitos problemas, mesmo que você esteja introduzindo uma segunda chave candidata, mas é muito mais fácil e compreensível ingressar em um campo do que em três.

Dan Blair
fonte
1
Essa estratégia desmorona quando você agora precisa percorrer 6 tabelas para unir as duas tabelas reais necessárias, porque as chaves compostas não foram propagadas. Também acaba exigindo o uso de loops / cursores para várias inserções, o que pode ser um enorme desempenho.
Tom H
2
Não sou grande demais para aprender algo novo. Eu adoraria ver um exemplo do que você está dizendo. Seria útil injetar um pouco de fato racional em alguns desses argumentos religiosos.
Dan Blair
0

Serei sincero sobre minha preferência por chaves naturais - use-as sempre que possível, pois elas facilitarão muito sua vida na administração de bancos de dados. Estabeleci em nossa empresa um padrão de que todas as tabelas têm as seguintes colunas:

  • ID da linha (GUID)
  • Criador (string; possui um padrão do nome do usuário atual ( SUSER_SNAME()em T-SQL))
  • Criado (DateTime)
  • Registro de data e hora

O ID da linha possui uma chave exclusiva por tabela e, em qualquer caso, é gerado automaticamente por linha (e as permissões impedem qualquer pessoa de editá-lo) e é razoavelmente garantido para ser exclusivo em todas as tabelas e bancos de dados. Se algum sistema ORM precisar de uma única chave de ID, essa é a única a ser usada.

Enquanto isso, o PK real é, se possível, uma chave natural. Minhas regras internas são algo como:

  • Pessoas - use chave substituta, por exemplo, INT. Se for interno, o GUID do usuário do Active Directory é uma escolha aceitável
  • Tabelas de pesquisa (por exemplo, StatusCodes) - use um código CHAR curto; é mais fácil lembrar do que as INTs e, em muitos casos, os formulários e os usuários do papel também o usarão por brevidade (por exemplo, Status = "E" para "Expirado", "A" para "Aprovado", "NADIS" para "Nenhum amianto detectado Na amostra ")
  • Tabelas de vinculação - combinação de FKs (por exemplo EventId, AttendeeId)

Então, idealmente, você acaba com um PK natural, legível por humanos e memorável, e um GUID de uma ID por tabela amigável para ORM.

Advertência: os bancos de dados que mantenho tendem a 100.000s de registros em vez de milhões ou bilhões; portanto, se você tiver experiência em sistemas maiores que contraindiquem meus conselhos, fique à vontade para me ignorar!

Keith Williams
fonte
1
Você está sugerindo a criação de ambos GUID e INT SKs para tabelas sem chave natural forte?
Você não precisa, mas os benefícios são: a) facilita a replicação, se necessário, b) ao lidar com o ORM, você pode atribuir um ID exclusivo ao seu objeto no código antes de salvá-lo (o que é útil se você precisa editar bastante o seu objeto, talvez salvando no cache da sessão, antes de salvá-lo). A chave é o INT nesta instância; o GUID é apenas um bônus.
Keith Williams