As chaves estrangeiras são realmente necessárias em um design de banco de dados?

109

Pelo que eu sei, as chaves estrangeiras (FK) são usadas para ajudar o programador a manipular os dados da maneira correta. Suponha que um programador já esteja fazendo isso da maneira certa, então realmente precisamos do conceito de chaves estrangeiras?

Existem outros usos para chaves estrangeiras? Estou faltando alguma coisa aqui?

Niyaz
fonte
2
Isso surge com frequência por aqui. Eu culpo Joel Spolsky :-). Existem muitas respostas boas aqui; em vez de redigitar o meu, darei a você apenas um link: stackoverflow.com/questions/83147/whats-wrong-with-foreign-keys
SquareCog
70
“Suponha que um programador já esteja realmente fazendo isso da maneira certa” - nem consigo imaginar tal cenário.
recursivo de
11
"Chave estrangeira" é uma ideia, não uma tecnologia. É uma regra relacional. Sua pergunta é realmente sobre se você deve tentar impor a regra em seu código ou deixar o banco de dados ajudá-lo. Quando a simultaneidade está envolvida, é melhor permitir que o mecanismo de banco de dados aplique a regra, uma vez que ele está ciente de TUDO que acontece no banco de dados, enquanto seu código não pode estar ciente.
Triynko
5
@lubos & cdeszaq. Na verdade, É uma regra relacional ... é um subconjunto da regra 10 dos "Mandamentos Twleve" de Codd ... "Independência de Integridade", que basicamente diz que a integridade relacional do RDBMS deve ser mantida independentemente de qualquer aplicativo que o acesse, que é exatamente o que eu estava explicando de uma forma fácil de entender. Esta regra é implementada por, entre outras coisas, restrições de chave estrangeira. Portanto, sim, a ideia de uma chave estrangeira é "uma" regra relacional.
Triynko
1
@lubos: Para esclarecer, você está falando sobre se vai ou não usar um recurso específico, mas estou falando sobre se a presença desse recurso é necessária para ter um RDBMS completo e totalmente funcional. Restrições referenciais, se e quando você optar por usá-las, é algo que deve ser aplicado no RDBMS (ao invés do aplicativo), portanto, é um recurso que deve estar lá e, nesse sentido, é um requisito do modelo relacional se você vai desenvolver um RDBMS completo.
Triynko,

Respostas:

102

As chaves estrangeiras ajudam a reforçar a integridade referencial no nível dos dados. Eles também melhoram o desempenho porque normalmente são indexados por padrão.

John Topley
fonte
52
Se você precisa de um índice, crie um, este não deve ser o motivo principal para FKs. (Na verdade, em certas circunstâncias (mais inserções do que seleções, por exemplo) manter um FK pode ser mais lento.)
Robert,
7
Essa é uma resposta horrível, os FKs geralmente podem adicionar sobrecarga extra, não melhorar o desempenho.
Agile Jedi
No SQL-Server, eles não são indexados por padrão no referee ou no referrer. sqlskills.com/blogs/kimberly/…
user420667
1
Nem no Oracle; você mesmo deve criar índices (nas colunas FK).
Littlefoot de
58

As chaves estrangeiras também podem ajudar o programador a escrever menos código usando coisas como ON DELETE CASCADE. Isso significa que se você tiver uma tabela contendo usuários e outra contendo pedidos ou algo assim, a exclusão de um usuário pode excluir automaticamente todos os pedidos que apontam para aquele usuário.

Greg Hewgill
fonte
3
@Greg Hewgill Isso pode levar a muitos problemas. Você deve ter muito cuidado com pensamentos como DELETE CASCADE, pois em muitos casos, você deseja manter os pedidos criados por um usuário ao excluí-lo.
Kibbee de
8
Embora isso provavelmente deva ser tratado na camada de lógica de negócios. Decidir se deve ou não manter registros filhos relacionados não é exatamente o mesmo que garantir que nenhum valor viole relacionamentos de chave estrangeira.
Codewerks de
5
O outro problema é a auditoria, se a auditoria não for feita no nível de banco de dados, atualizações ou exclusões em cascata invalidarão sua trilha de auditoria.
si618
@Codewerks: a lógica de negócios pode estar no banco de dados.
Fantius
44

Não consigo imaginar projetar um banco de dados sem chaves estrangeiras. Sem eles, eventualmente você cometerá um erro e corromperá a integridade de seus dados.

Eles não são necessários , a rigor, mas os benefícios são enormes.

Tenho quase certeza de que o FogBugz não possui restrições de chave estrangeira no banco de dados. Eu estaria interessado em ouvir como a equipe da Fog Creek Software estrutura seu código para garantir que eles nunca apresentarão uma inconsistência.

Eric Z Beard
fonte
43
Joel: "Até agora nunca tivemos um problema." Até agora, nunca dirigi contra um poste de luz. Mas ainda acho uma boa ideia usar cintos de segurança ;-)
Tony Andrews
2
Pode ser que você nunca VIU o problema, mas pode estar aí ... A maioria dos bancos de dados usa uma convenção como id_xxx que é exatamente a mesma que ixXXX
FerranB
1
@Joel: Convenções de nomenclatura no lugar da aplicação de regras? É melhor acabar com o tipo enquanto você está nisso.
jcollum
8
@Eric: Você está considerando o Fog Creek como uma espécie de avatar de desenvolvimento de software aqui. Se você dissesse "Uma empresa na cidade de Nova York não possui chaves estrangeiras em seu banco de dados ...", todos diríamos "E?"
jcollum
3
Eric: FogBugz usa uma convenção de nomenclatura para chaves estrangeiras. Por exemplo, ixBug é entendido como um índice na chave primária da tabela Bug. Até agora, nunca tivemos um problema. - Joel Spolsky
Sam Saffron
40

Um esquema de banco de dados sem restrições FK é como dirigir sem cinto de segurança.

Um dia, você vai se arrepender. Não gastar aquele tempo extra nos fundamentos do design e na integridade dos dados é uma maneira segura de garantir dores de cabeça mais tarde.

Você aceitaria um código em seu aplicativo que fosse tão desleixado? Isso acessou diretamente os objetos membros e modificou as estruturas de dados diretamente.

Por que você acha que isso se tornou difícil e até mesmo inaceitável nas línguas modernas?

Cara
fonte
2
+1 para uma boa analogia entre encapsulamento e relacionamentos FK / PK.
jcollum
21

Sim.

  1. Eles mantêm você honesto
  2. Eles mantêm os novos desenvolvedores honestos
  3. Você pode fazer ON DELETE CASCADE
  4. Eles ajudam você a gerar diagramas legais que explicam os links entre as tabelas
csmba
fonte
1
o que você quer dizer com honestidade?
dspacejs
Honesto com a concepção, eu acho. Ele evita que você trapaceie com os dados, fazendo uma programação rápida e ineficaz.
Oreste Viron
13

Suponha que um programador já esteja fazendo isso da maneira certa

Fazer tal suposição parece-me uma ideia extremamente ruim; em geral, o software apresenta muitos erros.

E esse é o ponto, realmente. Os desenvolvedores não conseguem fazer as coisas direito, portanto, garantir que o banco de dados não seja preenchido com dados ruins é uma coisa boa.

Embora em um mundo ideal, as junções naturais usariam relacionamentos (ou seja, restrições FK) em vez de nomes de coluna correspondentes. Isso tornaria os FKs ainda mais úteis.

DrPizza
fonte
2
Bom ponto, seria bom juntar duas tabelas com "ON [Relacionamento]" ou alguma outra palavra-chave e deixar o banco de dados descobrir quais colunas estão envolvidas. Parece muito razoável, na verdade.
jcollum
13

Pessoalmente, sou a favor das chaves estrangeiras porque formalizam a relação entre as tabelas. Sei que sua pergunta pressupõe que o programador não está apresentando dados que violariam a integridade referencial, mas já vi muitos casos em que a integridade referencial de dados é violada, apesar das melhores intenções!

Restrições de chave pré-estrangeira (também conhecidas como integridade referencial declarativa ou DRI) muito tempo foi gasto na implementação dessas relações usando gatilhos. O fato de podermos formalizar o relacionamento por meio de uma restrição declarativa é muito poderoso.

@John - Outros bancos de dados podem criar índices para chaves estrangeiras automaticamente, mas o SQL Server não. No SQL Server, os relacionamentos de chave estrangeira são apenas restrições. Você deve definir seu índice em chaves estrangeiras separadamente (o que pode ser útil).

Edit: Gostaria de acrescentar que, IMO, o uso de chaves estrangeiras no suporte de ON DELETE ou ON UPDATE CASCADE não é necessariamente uma coisa boa. Na prática, descobri que a cascata na exclusão deve ser considerada cuidadosamente com base na relação dos dados - por exemplo, você tem um pai-filho natural onde isso pode estar OK ou a tabela relacionada é um conjunto de valores de pesquisa. O uso de atualizações em cascata implica que você está permitindo que a chave primária de uma tabela seja modificada. Nesse caso, tenho uma discordância filosófica geral de que a chave primária de uma tabela não deve mudar. As chaves devem ser inerentemente constantes.

Peter Meyer
fonte
9

Sem uma chave estrangeira, como saber se dois registros em tabelas diferentes estão relacionados?

Acho que você está se referindo à integridade referencial, em que o registro filho não pode ser criado sem um registro pai existente, etc. Muitas vezes, são conhecidas como restrições de chave estrangeira - mas não devem ser confundidas com a existência de chaves estrangeiras em o primeiro lugar.

Samjudson
fonte
8

Existe uma vantagem em não ter chaves estrangeiras? A menos que você esteja usando um banco de dados de baixa qualidade, os FKs não são tão difíceis de configurar. Então, por que você teria uma política de evitá-los? Uma coisa é ter uma convenção de nomenclatura que diz que uma coluna faz referência a outra, outra é saber que o banco de dados está realmente verificando esse relacionamento para você.

Tundey
fonte
8

Suponho que você esteja falando sobre restrições de chave estrangeira impostas pelo banco de dados . Você provavelmente já está usando chaves estrangeiras, apenas não informou ao banco de dados sobre isso.

Suponha que um programador já esteja fazendo isso da maneira certa, então realmente precisamos do conceito de chaves estrangeiras?

Teoricamente, não. No entanto, nunca houve um software sem bugs.

Bugs no código do aplicativo normalmente não são tão perigosos - você identifica o bug e o corrige e, depois disso, o aplicativo é executado sem problemas novamente. Mas se um bug permite que dados corrompidos entrem no banco de dados, então você está preso a ele! É muito difícil recuperar dados corrompidos no banco de dados.

Considere se um bug sutil no FogBugz permitiu que uma chave estrangeira corrompida fosse escrita no banco de dados. Pode ser fácil corrigir o bug e enviar rapidamente a correção para os clientes em uma versão de correção de bug. No entanto, como os dados corrompidos em dezenas de bancos de dados devem ser corrigidos? O código correto agora pode quebrar repentinamente porque as suposições sobre a integridade das chaves estrangeiras não são mais válidas.

Em aplicativos da web, você normalmente tem apenas um programa falando com o banco de dados, portanto, há apenas um lugar onde bugs podem corromper os dados. Em um aplicativo corporativo, pode haver vários aplicativos independentes se comunicando com o mesmo banco de dados (sem mencionar as pessoas que trabalham diretamente com o shell do banco de dados). Não há como ter certeza de que todos os aplicativos seguem as mesmas premissas sem bugs, sempre e para sempre.

Se as restrições forem codificadas no banco de dados, o pior que pode acontecer com os bugs é que o usuário veja uma mensagem de erro feia sobre alguma restrição SQL não satisfeita. Isso é muito preferível a permitir que os dados sejam interrompidos em seu banco de dados corporativo, onde isso, por sua vez, quebrará todos os seus aplicativos ou apenas levará a todos os tipos de saída errada ou enganosa.

Ah, e as restrições de chave estrangeira também melhoram o desempenho porque são indexadas por padrão. Não consigo pensar em nenhuma razão para não usar restrições de chave estrangeira.

JacquesB
fonte
7

FKs são muito importantes e devem sempre existir em seu esquema, a menos que você seja o eBay .

Cherouvim
fonte
2
esse link é realmente extremamente fascinante ... eu realmente gostaria de saber mais detalhes e estou um pouco com medo de usar o ebay agora. para outras pessoas: clique na 4ª pergunta para ver o que ele diz sobre a estrutura do banco de dados. vale a pena assistir a entrevista inteira. também ...unibrow
gloomy.penguin
6

Acho que alguma coisa em algum ponto deve ser responsável por garantir relacionamentos válidos.

Por exemplo, Ruby on Rails não usa chaves estrangeiras, mas valida todos os relacionamentos por si só. Se você só acessa seu banco de dados a partir desse aplicativo Ruby on Rails, tudo bem.

Entretanto, se você tiver outros clientes que estão gravando no banco de dados, então, sem as chaves estrangeiras, eles precisam implementar sua própria validação. Você então tem duas cópias do código de validação que são provavelmente diferentes, o que qualquer programador deve ser capaz de dizer é um pecado capital.

Nesse ponto, as chaves estrangeiras são realmente necessárias, pois permitem que você mova a responsabilidade para um único ponto novamente.

Orion Edwards
fonte
2
É como uma cebola. FKs são a última camada de defesa. A menos que seja um banco de dados local embutido, aplicativos que tentam fazer integridade referencial são sempre uma má ideia.
Fabricio Araujo
5

As chaves estrangeiras permitem que alguém que nunca viu seu banco de dados antes determine a relação entre as tabelas.

Tudo pode estar bem agora, mas pense no que acontecerá quando o seu programador sair e outra pessoa assumir.

As chaves estrangeiras permitirão que eles entendam a estrutura do banco de dados sem vasculhar milhares de linhas de código.

Craig
fonte
5

Pelo que eu sei, as chaves estrangeiras são usadas para ajudar o programador a manipular os dados da maneira correta.

Os FKs permitem que o DBA proteja a integridade dos dados da trapalhada dos usuários quando o programador não o faz e, às vezes, protege contra a trapalhada dos programadores.

Suponha que um programador já esteja fazendo isso da maneira certa, então realmente precisamos do conceito de chaves estrangeiras?

Os programadores são mortais e falíveis. Os FKs são declarativos, o que os torna mais difíceis de errar .

Existem outros usos para chaves estrangeiras? Estou faltando alguma coisa aqui?

Embora não seja por isso que foram criados, os FKs fornecem dicas confiáveis ​​e fortes para ferramentas de diagramação e construtores de consultas. Isso é passado para os usuários finais, que precisam desesperadamente de dicas confiáveis ​​e fortes.

Peter Wone
fonte
Esta é uma ótima resposta.
Dan Lugg
4

Eles não são estritamente necessários, da mesma forma que os cintos de segurança não são estritamente necessários. Mas eles podem realmente evitar que você faça algo estúpido que bagunce seu banco de dados.

É muito mais agradável depurar um erro de restrição FK do que reconstruir uma exclusão que interrompeu seu aplicativo.

Mark Harrison
fonte
4

Eles são importantes porque seu aplicativo não é a única maneira pela qual os dados podem ser manipulados no banco de dados. Seu aplicativo pode lidar com a integridade referencial da maneira mais honesta que desejar, mas basta um bozo com os privilégios corretos para vir e emitir um comando de inserção, exclusão ou atualização no nível do banco de dados, e toda a aplicação de integridade referencial do aplicativo é ignorada. Colocar restrições FK no nível do banco de dados significa que, barrando este bozo escolhendo desabilitar a restrição FK antes de emitir seu comando, a restrição FK fará com que uma instrução de inserção / atualização / exclusão incorreta falhe com uma violação de integridade referencial.

Mike McAllister
fonte
3

Eu penso nisso em termos de custo / benefício ... No MySQL , adicionar uma restrição é uma única linha adicional de DDL . São apenas algumas palavras-chave e alguns segundos de reflexão. Esse é o único "custo" na minha opinião ...

As ferramentas adoram chaves estrangeiras. As chaves estrangeiras evitam dados inválidos (ou seja, linhas órfãs) que podem não afetar a lógica de negócios ou a funcionalidade e, portanto, passam despercebidos e aumentam. Também evita que os desenvolvedores que não estão familiarizados com o esquema implementem pedaços inteiros de trabalho sem perceber que estão perdendo um relacionamento. Talvez tudo esteja ótimo dentro do escopo de seu aplicativo atual, mas se você perdeu algo e algum dia algo inesperado é adicionado (pense em um relatório sofisticado), você pode estar em um ponto onde terá que limpar manualmente os dados ruins que foram acumulados desde o início do esquema sem uma verificação forçada do banco de dados.

O pouco tempo que leva para codificar o que já está em sua cabeça quando você está montando as coisas pode economizar para você ou para outra pessoa muitos meses ou anos de tristeza no caminho.

A questão:

Existem outros usos para chaves estrangeiras? Estou faltando alguma coisa aqui?

Está um pouco carregado. Insira comentários, indentação ou nomenclatura de variáveis ​​no lugar de "chaves estrangeiras" ... Se você já entendeu perfeitamente o assunto em questão, "não adianta" para você.

danb
fonte
2

Redução de entropia. Reduza a possibilidade de ocorrerem cenários caóticos no banco de dados. Temos dificuldade em considerar todas as possibilidades, então, na minha opinião, a redução da entropia é fundamental para a manutenção de qualquer sistema.

Quando fazemos uma suposição, por exemplo: cada pedido tem um cliente que a suposição deve ser aplicada por algo . Em bancos de dados, esse "algo" são chaves estrangeiras.

Acho que vale a pena compensar a velocidade de desenvolvimento. Claro, você pode codificar mais rápido sem eles e é provavelmente por isso que algumas pessoas não os usam. Pessoalmente, matei um certo número de horas com NHibernate e algumas restrições de chave estrangeira que ficam irritadas quando eu executo alguma operação. NO ENTANTO, eu sei qual é o problema, então é menos problemático. Estou usando ferramentas normais e existem recursos para me ajudar a contornar isso, possivelmente até mesmo pessoas para ajudar!

A alternativa é permitir que um bug entre no sistema (e com tempo suficiente, isso acontecerá) onde uma chave estrangeira não foi definida e seus dados se tornaram inconsistentes. Então, você recebe um relatório de bug incomum, investiga e "OH". O banco de dados está ferrado. Agora, quanto tempo isso vai demorar para consertar?

Trivial
fonte
1

Você pode ver as chaves estrangeiras como uma restrição que,

  • Ajude a manter a integridade dos dados
  • Mostre como os dados estão relacionados entre si (o que pode ajudar a aplicar a lógica e as regras de negócios)
  • Se usado corretamente, pode ajudar a aumentar a eficiência com a qual os dados são buscados nas tabelas.
Pascal
fonte
1

Atualmente, não usamos chaves estrangeiras. E na maior parte não nos arrependemos.

Dito isso, é provável que comecemos a usá-los muito mais em um futuro próximo por vários motivos, ambos por motivos semelhantes:

  1. Diagramação. É muito mais fácil produzir um diagrama de um banco de dados se houver relacionamentos de chave estrangeira usados ​​corretamente.

  2. Suporte de ferramenta. É muito mais fácil construir modelos de dados usando o Visual Studio 2008 que podem ser usados ​​para LINQ to SQL se houver relacionamentos de chave estrangeira adequados.

Portanto, acho que meu ponto é que descobrimos que, se estamos fazendo muito trabalho manual de SQL (construir consulta, executar consulta, blahblahblah), as chaves estrangeiras não são necessariamente essenciais. Depois que você começa a usar as ferramentas, porém, elas se tornam muito mais úteis.

John Christensen
fonte
1
Trabalho em sistemas que não os utilizam. E eu me arrependo regularmente. Já vi mais casos em que posso contar com dados sem sentido que teriam sido evitados por restrições adequadas.
recursivo de
E tendo trabalhado com chaves estrangeiras em nosso projeto atual por quase seis meses, concordo totalmente com este comentário.
John Christensen de
1

A melhor coisa sobre restrições de chave estrangeira (e restrições em geral, na verdade) é que você pode confiar nelas ao escrever suas consultas. Muitas consultas podem se tornar muito mais complicadas se você não puder confiar no modelo de dados que mantém "verdadeiro".

No código, geralmente obteremos apenas uma exceção lançada em algum lugar - mas no SQL , geralmente obteremos apenas as respostas "erradas".

Em teoria, o SQL Server poderia usar restrições como parte de um plano de consulta - mas, exceto pelas restrições de verificação para particionamento, não posso dizer que já tenha testemunhado isso.

Mark Brackett
fonte
As restrições de exclusividade indicam alta cardinalidade que é usada pelo otimizador ao selecionar um mecanismo de junção.
Peter Wone em
1

As chaves estrangeiras nunca foram explícitas (tabela FOREIGN KEY REFERENCES (coluna)) declaradas nos projetos (aplicativos de negócios e sites de redes sociais) nos quais trabalhei.

Mas sempre houve uma espécie de convenção de nomear colunas que eram chaves estrangeiras.

É como a normalização do banco de dados - você tem que saber o que está fazendo e quais são as consequências disso (principalmente desempenho).

Estou ciente das vantagens das chaves estrangeiras (integridade de dados, índice para coluna de chave estrangeira, ferramentas que reconhecem o esquema do banco de dados), mas também tenho medo de usar chaves estrangeiras como regra geral.

Além disso, vários mecanismos de banco de dados podem servir chaves estrangeiras de uma maneira diferente, o que pode levar a erros sutis durante a migração.

A remoção de todos os pedidos e faturas de clientes excluídos com ON DELETE CASCADE é o exemplo perfeito de um esquema de banco de dados bonito, mas mal projetado.

Grzegorz Gierlik
fonte
0

Sim. O ON DELETE [RESTRICT | CASCADE] impede os desenvolvedores de perder dados, mantendo os dados limpos. Recentemente, entrei para uma equipe de desenvolvedores Rails que não se concentrava em restrições de banco de dados, como chaves estrangeiras.

Felizmente, encontrei estes: http://www.redhillonrails.org/foreign_key_associations.html - Os plug-ins do RedHill on Ruby on Rails geram chaves estrangeiras usando a convenção sobre o estilo de configuração . Uma migração com product_id criará uma chave estrangeira para o id na tabela de produtos .

Confira os outros ótimos plug-ins no RedHill , incluindo migrações envolvidas em transações.

Peter Mortensen
fonte
0

Se você planeja gerar seu código de acesso a dados, ou seja, Entity Framework ou qualquer outro ORM, você perderá totalmente a capacidade de gerar um modelo hierárquico sem chaves estrangeiras

Mike Griffin
fonte