Quero saber se as chaves primárias compostas são uma prática ruim e, se não, em quais cenários é recomendável usar.
Minha pergunta é baseada neste artigo
A parte sobre chaves primárias compostas:
Má prática nº 6: chaves primárias compostas
Esse é um ponto controverso, já que muitos projetistas de bancos de dados falam hoje em dia sobre o uso de um campo gerado automaticamente de ID de número inteiro como chave primária, em vez de um campo composto definido pela combinação de dois ou mais campos. Atualmente, isso é definido como a “melhor prática” e, pessoalmente, eu tendem a concordar com isso.
No entanto, isso é apenas uma convenção e, é claro, os DBEs permitem a definição de chaves primárias compostas, que muitos designers consideram inevitáveis. Portanto, como na redundância, as chaves primárias compostas são uma decisão de design.
Cuidado, no entanto, se é esperado que sua tabela com uma chave primária composta tenha milhões de linhas, o índice que controla a chave composta pode crescer até um ponto em que o desempenho da operação CRUD é muito reduzido. Nesse caso, é muito melhor usar uma chave primária de ID inteiro simples, cujo índice será compacto o suficiente e estabelecer as restrições DBE necessárias para manter a exclusividade.
fonte
Respostas:
Dizer que o uso de
"Composite keys as PRIMARY KEY is bad practice"
é um total absurdo!Os compostos
PRIMARY KEY
são frequentemente uma "coisa boa" e a única maneira de modelar situações naturais que ocorrem na vida cotidiana!Pense no exemplo clássico de ensino de bancos de dados-101 de estudantes e cursos e nos muitos cursos realizados por muitos estudantes!
Crie tabelas de curso e aluno:
Vou dar o exemplo no dialeto do PostgreSQL (e MySQL ) - deve funcionar para qualquer servidor com alguns ajustes.
Agora, você obviamente quer manter o controle de quais estudante está tomando qual curso - então você tem o que é chamado um
joining table
(também chamadoslinking
,many-to-many
oum-to-n
tabelas). Eles também são conhecidos comoassociative entities
no jargão mais técnico!Um curso pode ter muitos alunos.
1 aluno pode fazer muitos cursos.
Então, você cria uma tabela de junção
Agora, a única maneira de dar uma sensata a esta tabela
PRIMARY KEY
é fazer dissoKEY
uma combinação de curso e aluno. Dessa forma, você não pode obter:uma duplicata da combinação de alunos e cursos
um curso só pode ter o mesmo aluno matriculado uma vez e
um aluno só pode se inscrever no mesmo curso apenas uma vez
você também tem uma pesquisa pronta
KEY
no curso por aluno - também conhecido como índice de cobertura ,é trivial encontrar cursos sem alunos e estudantes que não estão fazendo nenhum curso!
- O exemplo db-fiddle possui a restrição PK dobrada na CREATE TABLE - Isso pode ser feito de qualquer maneira. Prefiro ter tudo na instrução CREATE TABLE.
Agora, você poderia, se estivesse achando que as pesquisas por aluno por curso eram lentas, use
UNIQUE INDEX
on (sc_student_id, sc_course_id).Não é nenhuma bala de prata para a adição de índices - que vai fazer
INSERT
s eUPDATE
mais lento, mas o grande benefício da enorme decrescentesSELECT
vezes! Cabe ao desenvolvedor decidir indexar, considerando seu conhecimento e experiência, mas dizer quePRIMARY KEY
s compostos são sempre ruins é simplesmente errado.No caso de unir tabelas, elas geralmente são as únicas
PRIMARY KEY
que fazem sentido! As tabelas de junção também são frequentemente a única maneira de modelar o que acontece nos negócios ou na natureza ou em praticamente todas as esferas em que consigo pensar!Esse PK também é útil, pois
covering index
pode ajudar a acelerar as pesquisas. Nesse caso, seria particularmente útil se alguém estivesse pesquisando regularmente (id do curso, id do aluno) o que, imaginamos, pode ser o caso!Este é apenas um pequeno exemplo de onde um composto
PRIMARY KEY
pode ser uma boa idéia e a única maneira sensata de modelar a realidade! Do alto da minha cabeça, consigo pensar em muitos mais.Um exemplo do meu próprio trabalho!
Considere uma tabela de voo contendo um flight_id, uma lista de aeroportos de partida e chegada e os horários relevantes e, em seguida, também uma tabela de tripulação de cabine com tripulantes!
A única maneira sensata de modelar isso é ter uma tabela de flight_crew com o flight_id e o crew_id como atributos, e o único são
PRIMARY KEY
é usar a chave composta dos dois campos!fonte
id
chave primária e um índice exclusivocs_student_id
cs_course_id
e tenha os mesmos resultados?Minha opinião semi-educada: uma "chave primária" não precisa ser a única chave exclusiva usada para procurar dados na tabela, embora as ferramentas de gerenciamento de dados o ofereçam como seleção padrão. Portanto, para optar por ter um composto de duas colunas ou um número aleatório (provavelmente serial) gerado como a chave da tabela, você pode ter duas chaves diferentes ao mesmo tempo.
Se os valores dos dados incluírem um termo exclusivo adequado que possa representar a linha, prefiro declarar isso como "chave primária", mesmo que composta, do que usar uma chave "sintética". A chave sintética pode ter um desempenho melhor por razões técnicas, mas minha própria opção padrão é designar e usar o termo real como chave primária, a menos que você realmente precise seguir o outro caminho para fazer o serviço funcionar.
Um Microsoft SQL Server possui o recurso distinto, mas relacionado, do "índice clusterizado" que controla o armazenamento físico de dados em ordem de índice e também é usado dentro de outros índices. Por padrão, uma chave primária é criada como um índice em cluster, mas você pode escolher não em cluster, preferencialmente depois de criar o índice em cluster. Portanto, você pode ter uma coluna de identidade inteira gerada como índice clusterizado e, digamos, o nome do arquivo nvarchar (128 caracteres) como chave primária. Isso pode ser melhor porque a chave de índice em cluster é estreita, mesmo se você armazenar o nome do arquivo como o termo de chave estrangeira em outras tabelas - embora este exemplo seja um bom exemplo para não fazer isso.
Se o seu design envolve a importação de tabelas de dados que incluem uma chave primária inconveniente para identificar dados relacionados, você está praticamente preso a isso.
https://www.techopedia.com/definition/5547/primary-key descreve um exemplo de escolha entre armazenar dados com o número de segurança social de um cliente como a chave do cliente em todas as tabelas de dados ou gerar um customer_id arbitrário quando você registre-os. Na verdade, esse é um abuso grave do SSN, além de funcionar ou não; é um valor de dados pessoais e confidenciais.
Portanto, uma vantagem de usar um fato do mundo real como chave é que, sem voltar à tabela "Cliente", você pode recuperar informações sobre elas em outras tabelas - mas também é um problema de segurança de dados.
Além disso, você terá problemas se o SSN ou outra chave de dados tiver sido gravada incorretamente, portanto, você terá o valor errado em 20 tabelas restritas, em vez de apenas no "Cliente". Enquanto o customer_id sintético não tem significado externo, não pode ter um valor errado.
fonte