Les clés étrangères sont-elles vraiment nécessaires dans une conception de base de données?

109

Autant que je sache, les clés étrangères (FK) sont utilisées pour aider le programmeur à manipuler correctement les données. Supposons qu'un programmeur fasse déjà cela de la bonne manière, alors avons-nous vraiment besoin du concept de clés étrangères?

Existe-t-il d'autres utilisations des clés étrangères? Est-ce que j'ai râté quelque chose?

Niyaz
la source
2
Cela revient souvent ici. Je blâme Joel Spolsky :-). Il y a beaucoup de bonnes réponses ici; plutôt que de retaper le mien, je vais juste vous donner un lien: stackoverflow.com/questions/83147/whats-wrong-with-foreign-keys
SquareCog
70
"Supposons qu'un programmeur fasse déjà cela de la bonne manière" - je ne peux même pas imaginer un tel scénario.
récursif le
11
La "clé étrangère" est une idée, pas une technologie. C'est une règle relationnelle. Votre question est vraiment de savoir si vous devez essayer d'appliquer la règle dans votre code ou laisser la base de données vous aider. Lorsque la concurrence est impliquée, il est préférable de laisser le moteur de base de données appliquer la règle, car il est conscient de TOUT ce qui se passe dans la base de données, alors que votre code ne peut pas être au courant.
Triynko
5
@lubos & cdeszaq. En fait, c'est une règle relationnelle ... c'est un sous-ensemble de la règle 10 des "Twleve Commandments" de Codd ... "Integrity Independence", qui dit fondamentalement que l'intégrité relationnelle du SGBDR doit être maintenue indépendamment de toute application qui y accède, ce qui c'est exactement ce que j'expliquais d'une manière facile à comprendre. Cette règle est implémentée, entre autres, par des contraintes de clé étrangère. Alors oui, l'idée d'une clé étrangère est "une" règle relationnelle.
Triynko
1
@lubos: Pour clarifier, vous parlez de savoir si vous allez utiliser ou non une fonctionnalité particulière, mais je parle de savoir si la présence de cette fonctionnalité est nécessaire pour avoir un SGBDR complet et entièrement fonctionnel. Les contraintes référentielles, si et quand vous choisissez de les utiliser, sont quelque chose qui devrait être appliqué dans le SGBDR (plutôt que dans l'application), c'est donc une fonctionnalité qui devrait être là, et en ce sens c'est une exigence du modèle relationnel si vous allez développer un SGBDR complet.
Triynko

Réponses:

102

Les clés étrangères aident à renforcer l'intégrité référentielle au niveau des données. Ils améliorent également les performances car ils sont normalement indexés par défaut.

John Topley
la source
52
Si vous avez besoin d'un index, créez-en un, cela ne devrait pas être la principale raison des FK. (En fait, dans certaines circonstances (plus d'inserts que de sélections par exemple), le maintien d'un FK peut être plus lent.)
Robert
7
C'est une réponse horrible que les FK peuvent généralement ajouter des frais généraux supplémentaires sans améliorer les performances.
Agile Jedi
Dans SQL-Server, ils ne sont indexés par défaut ni sur le référent ni sur le référent. sqlskills.com/blogs/kimberly/…
user420667
1
Ni dans Oracle; vous devez créer vous-même des index (sur les colonnes FK).
Littlefoot
58

Les clés étrangères peuvent également aider le programmeur à écrire moins de code en utilisant des choses comme ON DELETE CASCADE. Cela signifie que si vous avez une table contenant des utilisateurs et une autre contenant des commandes ou quelque chose, la suppression d'un utilisateur pourrait supprimer automatiquement toutes les commandes qui pointent vers cet utilisateur.

Greg Hewgill
la source
3
@Greg Hewgill Cela pourrait conduire pontentiellement à beaucoup de problèmes. Vous devez être très prudent avec des idées telles que DELETE CASCADE, car dans de nombreux cas, vous souhaitez conserver les commandes créées par un utilisateur lors de la suppression de l'utilisateur.
Kibbee
8
Bien que cela devrait probablement être géré dans la couche de logique métier. Décider de conserver ou non les enregistrements enfants associés n'est pas tout à fait la même chose que de s'assurer qu'aucune valeur ne viole les relations de clé étrangère.
Codewerks
5
L'autre problème est l'audit, si l'audit n'est pas effectué au niveau de la base de données, les mises à jour ou les suppressions en cascade invalideront votre piste d'audit.
si618
@Codewerks: la logique métier peut être dans la base de données.
Fantius
44

Je ne peux pas imaginer concevoir une base de données sans clés étrangères. Sans eux, vous finirez par faire une erreur et corrompre l'intégrité de vos données.

Ils ne sont pas obligatoires à proprement parler, mais les avantages sont énormes.

Je suis assez certain que FogBugz n'a pas de contraintes de clé étrangère dans la base de données. Je serais intéressé d'apprendre comment l'équipe de Fog Creek Software structure son code pour garantir qu'elle n'introduira jamais d'incohérence.

Eric Z Beard
la source
43
Joel: "Jusqu'à présent, nous n'avons jamais eu de problème." Jusqu'à présent, je ne suis jamais entré dans un lampadaire. Mais je pense toujours que c'est une bonne idée de porter la ceinture de sécurité ;-)
Tony Andrews
2
Peut-être que vous n'avez jamais vu le problème, mais peut-être qu'il est là ... La plupart des bases de données utilisent une convention comme id_xxx qui est exactement la même que ixXXX
FerranB
1
@Joel: Les conventions de dénomination au lieu de l'application des règles? Autant éliminer le type pendant que vous y êtes.
jcollum
8
@Eric: Vous considérez Fog Creek comme une sorte d'avatar du développement logiciel ici. Si vous disiez "Une entreprise à New York n'a pas de clés étrangères dans sa base de données ...", nous dirions tous "Et?"
jcollum
3
Eric: FogBugz utilise une convention de dénomination pour les clés étrangères. Par exemple, ixBug est compris comme un index dans la clé primaire de la table Bug. Jusqu'à présent, nous n'avons jamais eu de problème. - Joel Spolsky
Sam Saffron
40

Un schéma de base de données sans contraintes FK, c'est comme conduire sans ceinture de sécurité.

Un jour, vous le regretterez. Ne pas consacrer ce peu de temps supplémentaire aux principes de base de la conception et à l'intégrité des données est un moyen infaillible de garantir des maux de tête plus tard.

Accepteriez-vous du code dans votre application qui était aussi bâclé? Cela accédait directement aux objets membres et modifiait directement les structures de données.

Pourquoi pensez-vous que cela a été rendu difficile et même inacceptable dans les langues modernes?

Gars
la source
2
+1 pour une bonne analogie entre l'encapsulation et les relations FK / PK.
jcollum
21

Oui.

  1. Ils vous gardent honnête
  2. Ils gardent les nouveaux développeurs honnêtes
  3. Tu peux faire ON DELETE CASCADE
  4. Ils vous aident à générer de jolis diagrammes qui expliquent eux-mêmes les liens entre les tables
csmba
la source
1
qu'entendez-vous par honnêteté?
dspacejs
Honnête avec la conception, je suppose. Cela vous empêche de tricher avec les données en effectuant une programmation rapide et boiteuse.
Oreste Viron
13

Supposons qu'un programmeur fasse déjà cela de la bonne manière

Faire une telle supposition me paraît être une très mauvaise idée; en général, les logiciels sont extrêmement bogués.

Et c'est le point, vraiment. Les développeurs ne peuvent pas faire les choses correctement, donc s'assurer que la base de données ne peut pas être remplie de mauvaises données est une bonne chose.

Bien que dans un monde idéal, les jointures naturelles utiliseraient des relations (c'est-à-dire des contraintes FK) plutôt que des noms de colonnes correspondants. Cela rendrait les FK encore plus utiles.

DrPizza
la source
2
Bon point, ce serait bien de joindre deux tables avec "ON [Relationship]" ou un autre mot-clé et laisser la base de données déterminer quelles colonnes sont impliquées. Semble vraiment raisonnable.
jcollum
13

Personnellement, je suis favorable aux clés étrangères car cela formalise la relation entre les tables. Je me rends compte que votre question présuppose que le programmeur n'introduit pas de données qui violeraient l'intégrité référentielle, mais j'ai vu beaucoup trop de cas où l'intégrité référentielle des données est violée, malgré les meilleures intentions!

Les contraintes de clé pré-étrangère (c'est-à-dire l'intégrité référentielle déclarative ou DRI) ont été consacrées à l'implémentation de ces relations à l'aide de déclencheurs. Le fait que l'on puisse formaliser la relation par une contrainte déclarative est très puissant.

@John - D'autres bases de données peuvent créer automatiquement des index pour les clés étrangères, mais pas SQL Server. Dans SQL Server, les relations de clé étrangère ne sont que des contraintes. Vous devez définir votre index sur les clés étrangères séparément (ce qui peut être avantageux).

Edit: Je voudrais ajouter que, IMO, l'utilisation de clés étrangères à l'appui de ON DELETE ou ON UPDATE CASCADE n'est pas nécessairement une bonne chose. En pratique, j'ai trouvé que la cascade lors de la suppression devrait être soigneusement considérée en fonction de la relation des données - par exemple, avez-vous un parent-enfant naturel où cela peut être OK ou la table associée est-elle un ensemble de valeurs de recherche. L'utilisation de mises à jour en cascade implique que vous autorisez la modification de la clé primaire d'une table. Dans ce cas, j'ai un désaccord philosophique général en ce que la clé primaire d'une table ne doit pas changer. Les clés doivent être intrinsèquement constantes.

Peter Meyer
la source
9

Sans clé étrangère, comment savoir que deux enregistrements dans des tables différentes sont liés?

Je pense que vous faites référence à l'intégrité référentielle, où l'enregistrement enfant n'est pas autorisé à être créé sans enregistrement parent existant, etc. Celles-ci sont souvent appelées contraintes de clé étrangère - mais ne doivent pas être confondues avec l'existence de clés étrangères dans la première place.

Samjudson
la source
8

Y a-t-il un avantage à ne pas avoir de clés étrangères? À moins que vous n'utilisiez une base de données de merde, les FK ne sont pas si difficiles à configurer. Alors, pourquoi auriez-vous une politique pour les éviter? C'est une chose d'avoir une convention de dénomination qui dit qu'une colonne en référence une autre, c'est une autre de savoir que la base de données vérifie réellement cette relation pour vous.

Tundey
la source
8

Je suppose que vous parlez de contraintes de clé étrangère imposées par la base de données . Vous utilisez probablement déjà des clés étrangères, vous n'en avez simplement pas informé la base de données.

Supposons qu'un programmeur fasse déjà cela de la bonne manière, alors avons-nous vraiment besoin du concept de clés étrangères?

Théoriquement, non. Cependant, il n'y a jamais eu de logiciel sans bogues.

Les bogues dans le code de l'application ne sont généralement pas si dangereux - vous identifiez le bogue et le corrigez, puis l'application s'exécute à nouveau correctement. Mais si un bogue permet aux données currupt d'entrer dans la base de données, alors vous êtes coincé! Il est très difficile de récupérer des données corrompues dans la base de données.

Considérez si un bogue subtil dans FogBugz a permis l' écriture d' une clé étrangère corrompue dans la base de données. Il peut être facile de corriger le bogue et de transmettre rapidement le correctif aux clients dans une version de correction de bogue. Cependant, comment corriger les données corrompues dans des dizaines de bases de données? Le code correct peut maintenant se rompre soudainement parce que les hypothèses sur l'intégrité des clés étrangères ne tiennent plus.

Dans les applications Web, vous n'avez généralement qu'un seul programme parlant à la base de données, il n'y a donc qu'un seul endroit où des bogues peuvent corrompre les données. Dans une application d'entreprise, il peut y avoir plusieurs applications indépendantes parlant à la même base de données (sans parler des personnes travaillant directement avec le shell de la base de données). Il n'y a aucun moyen d'être sûr que toutes les applications suivent les mêmes hypothèses sans bogues, toujours et pour toujours.

Si des contraintes sont encodées dans la base de données, le pire qui puisse arriver avec les bogues est que l'utilisateur voit un message d'erreur affreux concernant une contrainte SQL non satisfaite. Ceci est de loin préférable à l'introduction de données currupt dans la base de données de votre entreprise, où elles interrompront à leur tour toutes vos applications ou conduiront simplement à toutes sortes de sorties erronées ou trompeuses.

Oh, et les contraintes de clé étrangère améliorent également les performances car elles sont indexées par défaut. Je ne vois aucune raison de ne pas utiliser de contraintes de clé étrangère.

JacquesB
la source
7

Les FK sont très importants et devraient toujours exister dans votre schéma, sauf si vous êtes eBay .

cherouvim
la source
2
ce lien est en fait extrêmement fascinant ... j'aimerais vraiment en savoir plus et j'ai un peu peur d'utiliser ebay maintenant. pour les autres: cliquez sur la 4e question pour voir ce qu'il dit sur leur structure de base de données. l'interview entière mérite cependant d'être regardée. aussi ...unibrow
gloomy.penguin
6

Je pense qu'une seule chose à un moment donné doit être responsable d'assurer des relations valables.

Par exemple, Ruby on Rails n'utilise pas de clés étrangères, mais il valide toutes les relations lui-même. Si vous n'accédez à votre base de données qu'à partir de cette application Ruby on Rails, c'est très bien.

Cependant, si vous avez d'autres clients qui écrivent dans la base de données, alors sans clés étrangères, ils doivent implémenter leur propre validation. Vous avez alors deux copies du code de validation qui sont très probablement différentes, ce que tout programmeur devrait être capable de dire est un péché cardinal.

À ce stade, les clés étrangères sont vraiment nécessaires, car elles vous permettent de déplacer à nouveau la responsabilité vers un seul point.

Orion Edwards
la source
2
C'est comme un oignon. Les FK sont la dernière couche de défense. À moins qu'il ne s'agisse d'une base de données locale intégrée, les applications qui tentent de faire de l'intégrité référentielle sont toujours une mauvaise idée.
Fabricio Araujo
5

Les clés étrangères permettent à quelqu'un qui n'a jamais vu votre base de données auparavant de déterminer la relation entre les tables.

Tout va peut-être bien maintenant, mais pensez à ce qui se passera lorsque votre programmeur partira et que quelqu'un d'autre devra prendre le relais.

Les clés étrangères leur permettront de comprendre la structure de la base de données sans parcourir des milliers de lignes de code.

Craig
la source
5

Pour autant que je sache, les clés étrangères sont utilisées pour aider le programmeur à manipuler correctement les données.

Les FK permettent au DBA de protéger l'intégrité des données contre les tâtonnements des utilisateurs lorsque le programmeur ne parvient pas à le faire, et parfois de se protéger contre les tâtonnements des programmeurs.

Supposons qu'un programmeur fasse déjà cela de la bonne manière, alors avons-nous vraiment besoin du concept de clés étrangères?

Les programmeurs sont mortels et faillibles. Les FK sont déclaratifs, ce qui les rend plus difficiles à bousiller.

Existe-t-il d'autres utilisations des clés étrangères? Est-ce que j'ai râté quelque chose?

Bien que ce ne soit pas la raison pour laquelle ils ont été créés, les FK fournissent des indications fiables et solides aux outils de création de diagrammes et aux générateurs de requêtes. Ceci est transmis aux utilisateurs finaux, qui ont désespérément besoin d'indices fiables et solides.

Peter Wone
la source
C'est une excellente réponse.
Dan Lugg
4

Ils ne sont pas strictement nécessaires, de la même manière que les ceintures de sécurité ne sont pas strictement nécessaires. Mais ils peuvent vraiment vous éviter de faire quelque chose de stupide qui gâche votre base de données.

C'est tellement plus agréable de déboguer une erreur de contrainte FK que de devoir reconstruire une suppression qui a cassé votre application.

Mark Harrison
la source
4

Ils sont importants, car votre application n'est pas le seul moyen de manipuler les données dans la base de données. Votre application peut gérer l'intégrité référentielle aussi honnêtement qu'elle le souhaite, mais il suffit d'un bozo avec les privilèges appropriés pour émettre une commande d'insertion, de suppression ou de mise à jour au niveau de la base de données, et toute application de l'intégrité référentielle de votre application est contournée. Mettre des contraintes FK au niveau de la base de données signifie que, à moins que ce bozo choisisse de désactiver la contrainte FK avant d'émettre sa commande, la contrainte FK provoquera l'échec d'une mauvaise instruction d'insertion / mise à jour / suppression avec une violation d'intégrité référentielle.

Mike McAllister
la source
3

J'y pense en termes de coût / bénéfice ... Dans MySQL , l'ajout d'une contrainte est une seule ligne supplémentaire de DDL . C'est juste une poignée de mots clés et quelques secondes de réflexion. C'est le seul "coût" à mon avis ...

Les outils aiment les clés étrangères. Les clés étrangères empêchent les mauvaises données (c'est-à-dire les lignes orphelines) qui peuvent ne pas affecter la logique ou la fonctionnalité métier et par conséquent passer inaperçues et s'accumuler. Cela empêche également les développeurs qui ne sont pas familiers avec le schéma d'implémenter des morceaux entiers de travail sans se rendre compte qu'il leur manque une relation. Peut-être que tout va bien dans le cadre de votre application actuelle, mais si vous avez manqué quelque chose et qu'un jour quelque chose d'inattendu est ajouté (pensez aux rapports sophistiqués), vous pourriez être dans un endroit où vous devez nettoyer manuellement les mauvaises données qui s'accumulent depuis la création. du schéma sans vérification forcée de la base de données.

Le peu de temps qu'il faut pour codifier ce qui est déjà dans votre tête lorsque vous mettez les choses ensemble pourrait vous épargner, à vous ou à quelqu'un d'autre, un tas de chagrins des mois ou des années plus tard.

La question:

Existe-t-il d'autres utilisations des clés étrangères? Est-ce que j'ai râté quelque chose?

C'est un peu chargé. Insérez des commentaires, des indentations ou des noms de variables à la place des "clés étrangères" ... Si vous comprenez déjà parfaitement la chose en question, cela ne vous sert à rien.

danb
la source
2

Réduction de l'entropie. Réduisez le risque que des scénarios chaotiques se produisent dans la base de données. Nous avons du mal car il considère toutes les possibilités, donc, à mon avis, la réduction de l'entropie est la clé du maintien de tout système.

Lorsque nous faisons une hypothèse par exemple: chaque commande a un client que l'hypothèse doit être renforcée par quelque chose . Dans les bases de données, ce "quelque chose" est des clés étrangères.

Je pense que cela vaut le compromis en termes de vitesse de développement. Bien sûr, vous pouvez coder plus rapidement avec eux et c'est probablement pourquoi certaines personnes ne les utilisent pas. Personnellement, j'ai tué un certain nombre d'heures avec NHibernate et une contrainte de clé étrangère qui se met en colère lorsque j'effectue une opération. CEPENDANT, je sais quel est le problème, donc c'est moins un problème. J'utilise des outils normaux et il existe des ressources pour m'aider à contourner ce problème, peut-être même des personnes pour m'aider!

L'alternative est de permettre à un bogue de s'infiltrer dans le système (et avec suffisamment de temps, ce sera le cas) où une clé étrangère n'est pas définie et vos données deviennent incohérentes. Ensuite, vous obtenez un rapport de bogue inhabituel, enquêter et "OH". La base de données est vissée. Maintenant, combien de temps cela prendra-t-il pour réparer?

Quibblesome
la source
1

Vous pouvez afficher les clés étrangères comme une contrainte qui,

  • Aide à maintenir l'intégrité des données
  • Montrer comment les données sont liées les unes aux autres (ce qui peut aider à appliquer la logique et les règles métier)
  • S'il est utilisé correctement, peut aider à augmenter l'efficacité avec laquelle les données sont extraites des tables.
Pascal
la source
1

Nous n'utilisons actuellement pas de clés étrangères. Et pour la plupart, nous ne le regrettons pas.

Cela dit, nous allons probablement commencer à les utiliser beaucoup plus dans un avenir proche pour plusieurs raisons, toutes deux pour des raisons similaires:

  1. Diagramme. Il est tellement plus facile de produire un diagramme d'une base de données si des relations de clé étrangère sont correctement utilisées.

  2. Support d'outils. Il est beaucoup plus facile de créer des modèles de données à l'aide de Visual Studio 2008 qui peuvent être utilisés pour LINQ to SQL s'il existe des relations de clé étrangère appropriées.

Donc, je suppose que mon point est que nous avons constaté que si nous faisons beaucoup de travail manuel SQL (requête de construction, requête d'exécution, blahblahblah), les clés étrangères ne sont pas nécessairement essentielles. Une fois que vous commencez à utiliser les outils, ils deviennent beaucoup plus utiles.

John Christensen
la source
1
Je travaille sur des systèmes qui ne les utilisent pas. Et je le regrette régulièrement. J'ai vu plus de cas où je peux compter des données non sensibles qui auraient été évitées par des contraintes appropriées.
récursif le
Et après avoir travaillé avec des clés étrangères sur notre projet actuel depuis près de six mois, je suis totalement d'accord avec ce commentaire.
John Christensen
1

La meilleure chose à propos des contraintes de clé étrangère (et des contraintes en général, en réalité) est que vous pouvez vous y fier lorsque vous écrivez vos requêtes. De nombreuses requêtes peuvent devenir beaucoup plus compliquées si vous ne pouvez pas vous fier au modèle de données "vrai".

Dans le code, nous obtiendrons généralement juste une exception lancée quelque part - mais en SQL , nous obtiendrons généralement les «mauvaises» réponses.

En théorie, SQL Server pourrait utiliser des contraintes dans le cadre d'un plan de requête - mais à l'exception des contraintes de vérification pour le partitionnement, je ne peux pas dire que j'aie jamais été témoin de cela.

Mark Brackett
la source
Les contraintes d'unicité indiquent une cardinalité élevée qui est utilisée par l'optimiseur pour sélectionner un mécanisme de jointure.
Peter Wone
1

Les clés étrangères n'avaient jamais été explicites (table (colonne) REFERENCES CLÉS ÉTRANGÈRES) déclarées dans les projets (applications métiers et sites de réseaux sociaux) sur lesquels j'ai travaillé.

Mais il y avait toujours une sorte de convention de dénomination des colonnes qui étaient des clés étrangères.

C'est comme avec la normalisation de base de données - vous devez savoir ce que vous faites et quelles en sont les conséquences (principalement les performances).

Je connais les avantages des clés étrangères (intégrité des données, index pour la colonne de clé étrangère, outils conscients du schéma de base de données), mais j'ai aussi peur d'utiliser des clés étrangères en règle générale.

De plus, divers moteurs de base de données pourraient servir des clés étrangères d'une manière différente, ce qui pourrait entraîner des bogues subtils lors de la migration.

La suppression de toutes les commandes et factures du client supprimé avec ON DELETE CASCADE est l'exemple parfait d'un schéma de base de données beau mais mal conçu.

Grzegorz Gierlik
la source
0

Oui. ON DELETE [RESTRICT | CASCADE] empêche les développeurs de bloquer les données, en gardant les données propres. J'ai récemment rejoint une équipe de développeurs Rails qui ne se concentrait pas sur les contraintes de base de données telles que les clés étrangères.

Heureusement, j'ai trouvé ceux-ci: http://www.redhillonrails.org/foreign_key_associations.html - Les plug-ins RedHill sur Ruby on Rails génèrent des clés étrangères en utilisant la convention sur le style de configuration . Une migration avec product_id créera une clé étrangère vers l' id dans la table products .

Découvrez les autres excellents plug-ins de RedHill , y compris les migrations intégrées dans des transactions.

Peter Mortensen
la source
0

Si vous prévoyez de générer votre code d'accès aux données, c'est-à-dire Entity Framework ou tout autre ORM, vous perdez entièrement la possibilité de générer un modèle hiérarchique sans clés étrangères

Mike Griffin
la source