Quel est le problème avec les clés étrangères?


259

Je me souviens avoir entendu Joel Spolsky mentionner dans le podcast 014 qu'il avait à peine utilisé une clé étrangère (si je me souviens bien). Cependant, ils me semblent assez vitaux pour éviter la duplication et les problèmes ultérieurs d'intégrité des données dans votre base de données.

Les gens ont-ils des raisons solides pour expliquer pourquoi (pour éviter une discussion conforme aux principes de Stack Overflow)?

Edit: "Je n'ai pas encore de raison de créer une clé étrangère, donc cela pourrait être ma première raison d'en créer une."


9
Je ne pense pas que Joel n'utilise pas de FK, c'est juste qu'il ne fait pas appliquer la base de données. Logiquement, ce sont toujours des FK!
Daren Thomas

6
Il dit qu'il n'utilise pas de clés étrangères, mais je suis d'accord avec Daren que ce qu'il veut dire, c'est qu'il n'utilise pas de clés étrangères CONTRAINTES. Une colonne d'une table dont les valeurs sont censées être extraites de la clé primaire / unique d'une autre table SONT des clés étrangères, que vous ajoutiez ou non la contrainte.
Tony Andrews

22
... Généralement, il est insensé de ne pas ajouter la contrainte: cela ASSURE l'intégrité à tout moment, même s'il y a un bug dans le code de l'application ou si vous travaillez en arrière-plan en faisant un "correctif" de données.
Tony Andrews

2
+1 Pour le commentaire de Tony. Il y a beaucoup trop de confusion entre la fonctionnalité et le concept logique des clés étrangères.
JohnFx

4
@DanMan, je ne sais pas où vous avez eu l'impression que je pense que. Je dis en fait ci-dessus "Généralement, il est insensé de ne pas ajouter la contrainte: il ASSURE l'intégrité à tout moment"
Tony Andrews

Réponses:


352

Raisons d'utiliser des clés étrangères:

  • vous n'obtiendrez pas de lignes orphelines
  • vous pouvez obtenir un bon comportement "en cas de suppression de cascade", en nettoyant automatiquement les tables
  • connaître les relations entre les tables de la base de données aide l'Optimizer à planifier vos requêtes pour une exécution plus efficace, car il est capable d'obtenir de meilleures estimations sur la cardinalité de jointure.
  • Les FK donnent un assez gros indice sur les statistiques les plus importantes à collecter sur la base de données, ce qui conduit à son tour à de meilleures performances
  • ils permettent toutes sortes de support généré automatiquement - les ORM peuvent se générer eux-mêmes, les outils de visualisation pourront créer de belles dispositions de schéma pour vous, etc.
  • une personne nouvelle dans le projet entrera plus rapidement dans le flux des choses car sinon les relations implicites sont explicitement documentées

Raisons de ne pas utiliser de clés étrangères:

  • vous faites travailler la base de données supplémentaire sur chaque opération CRUD car elle doit vérifier la cohérence FK. Cela peut être un gros coût si vous avez beaucoup de désabonnement
  • en imposant des relations, les FK spécifient un ordre dans lequel vous devez ajouter / supprimer des éléments, ce qui peut conduire au refus de la base de données de faire ce que vous voulez. (Certes, dans de tels cas, ce que vous essayez de faire est de créer une ligne orpheline, et ce n'est généralement pas une bonne chose). Cela est particulièrement douloureux lorsque vous effectuez de grandes mises à jour par lots et que vous chargez une table avant une autre, la deuxième table créant un état cohérent (mais devriez-vous faire ce genre de chose s'il y a une possibilité que le deuxième chargement échoue et que votre est maintenant incohérente?).
  • parfois vous savez à l'avance que vos données vont être sales, vous l'acceptez et vous voulez que la base de données l'accepte
  • vous êtes juste paresseux :-)

Je pense (je ne suis pas certain!) Que la plupart des bases de données établies fournissent un moyen de spécifier une clé étrangère qui n'est pas appliquée, et est simplement un peu de métadonnées. Étant donné que la non-application efface toutes les raisons de ne pas utiliser les FK, vous devriez probablement suivre cette voie si l'une des raisons de la deuxième section s'applique.


12
Bonne liste! Les DBM ne vérifieront pas la cohérence de la partie "R" de CRUD, donc je retirerais cette partie. De plus, c'est probablement un lavage parce que dans votre application, vous faites la même chose que le SGBD: vous vérifierez et vous assurerez que l'ID parent est valide avant CRD et c'est en fait plus lent que de le faire avec les DBM!
Matt Rogish

6
Que se passe-t-il si quelqu'un supprime le parent pendant que vous insérez des enfants? En ce moment, lorsque je soumets "ajouter un commentaire" - si vous avez déjà supprimé votre réponse, ce commentaire est désormais orphelin. Les FK l'auraient empêché. En outre, je pourrais simplement changer le parentID pour être tout ce que je veux. Quelqu'un doit vérifier. :)
Matt Rogish

7
Précisément - cela devrait être le travail de la base de données, car c'est le seul qui peut garantir la transactionnalité face à plusieurs clients simultanés.
SquareCog

3
+1 Excellente réponse - la deuxième raison de ne pas utiliser les contraintes FK pourrait être considérée comme «rend plus difficile la rupture de cohérence», ce qui semble être une bonne chose!
Bill Karwin

9
À mon avis, les avantages de l'utilisation de clés étrangères FAR l'emportent sur les avantages de ne pas les utiliser.
Nick Bedford

80

C'est une question d'éducation. Si, quelque part dans votre carrière éducative ou professionnelle, vous avez passé du temps à alimenter et à prendre soin de bases de données (ou à travailler en étroite collaboration avec des personnes talentueuses qui l'ont fait), les principes fondamentaux des entités et des relations sont bien ancrés dans votre processus de réflexion. Parmi ces rudiments se trouve comment / quand / pourquoi spécifier des clés dans votre base de données (primaire, étrangère et peut-être alternative). C'est une seconde nature.

Si, cependant, vous n'avez pas eu une telle expérience approfondie ou positive dans votre passé avec les efforts liés au SGBDR, alors vous n'avez probablement pas été exposé à de telles informations. Ou peut-être que votre passé inclut une immersion dans un environnement qui était vociférément anti-base de données (par exemple, "ces DBA sont des idiots - nous sommes peu, nous avons choisi quelques slingers de code java / c # pour sauver la journée"), auquel cas vous pourriez être opposé avec véhémence aux babillages obscurs de certains dweeb vous disant que les FK (et les contraintes qu'ils peuvent impliquer) sont vraiment importants si vous voulez juste écouter.

Quand ils étaient enfants, presque tout le monde a appris qu'il était important de se brosser les dents. Pouvez-vous vous en passer? Bien sûr, mais quelque part sur la ligne, vous aurez moins de dents disponibles que si vous vous étiez brossé après chaque repas. Si les mamans et les papas étaient suffisamment responsables pour couvrir la conception de la base de données ainsi que l'hygiène buccale, nous n'aurions pas cette conversation. :-)


61
Je vais utiliser la distillée "les clés étrangères sont comme se brosser les dents: allez-y, passez-en, mais attention quand vous souriez"
Mark Sowul

5
Personnellement, je trouve que les principes du SGBDR sont beaucoup plus simples et bien mieux définis que ceux de l'hygiène buccale
Ali Gangji

10 ans à l'avenir, je vais certainement avoir cette discussion sur la conception de la base de données avec mon fils / fille afin qu'il / elle ne gâche pas et finisse par être la raison du prochain crash de Wall Street en raison d'un problème de base de données.
VarunAgw

52

Je suis sûr qu'il existe de nombreuses applications où vous pouvez vous en tirer, mais ce n'est pas la meilleure idée. Vous ne pouvez pas toujours compter sur votre application pour gérer correctement votre base de données, et franchement, la gestion de la base de données ne devrait pas être très préoccupante pour votre application.

Si vous utilisez une base de données relationnelle, il semble que vous devriez y définir des relations . Malheureusement, cette attitude (vous n'avez pas besoin de clés étrangères) semble être adoptée par de nombreux développeurs d'applications qui préfèrent ne pas être gênés par des choses stupides comme l'intégrité des données (mais doivent le faire parce que leurs entreprises n'ont pas de développeurs de bases de données dédiés). Habituellement, dans les bases de données regroupées par ces types, vous avez la chance de ne disposer que de clés primaires;)


26
Je n'ai vraiment pas de gens qui n'ont pas de FK dans leur base de données. La dernière fois que j'ai travaillé avec quelqu'un qui ne l'avait pas, il a dit "non, nous appliquons cela dans la demande". Sauf que j'ai fait une enquête sur toutes les bases de données clients et j'ai trouvé que la plupart d'entre elles avaient des orphelins ...
ErikE

1
Cela semble généralement être le cas. Je pense que vous pourriez vous en sortir en appliquant UNIQUEMENT dans la base de données (tant que vos utilisateurs ne se soucient pas des exceptions d'exécution), mais avoir les deux est vraiment la seule façon de procéder.
AlexCuse

Tout est dans les transcriptions / la réponse d'Atwood "Atwood: ... sur la base des clés étrangères que vous avez définies dans les index, ils le comprennent ... Spolsky: [rires] En supposant que vous le faites. Atwood: Eh bien, en supposant que vous configurez votre base de données correctement ... "
MemeDeveloper

4
Les bases de données ne sont pas appelées relationnelles en raison des relations entre les tables (CHAQUE type de base de données a une sorte de relations entre les entités!), Mais parce que les tables elles-mêmes sont des relations , en termes mathématiques. Voir Wikipedia .
Massimiliano Kraus

41

Les clés étrangères sont essentielles à tout modèle de base de données relationnelle.


54
Le modèle, oui. L'implémentation, pas indispensable, juste probablement utile.
dkretz

4
Désolé, mais la raison principale pour laquelle les développeurs d'applications n'utilisent pas plus largement les systèmes de gestion de bases de données d'objets (alias bases de données NoSQL!) Est en raison de l'investissement dans les SGBDR. La plupart du temps, la base de données (et non le système de gestion de base de données) est un modèle objet de niveau intermédiaire impliquant souvent des caches distribués. C'est là que la suppression en cascade, la propriété et la synchronisation des modifications doivent se produire de toute façon. Le SGBDR est utilisé principalement pour la persistance de ce modèle d'objet, et généralement après un exercice ORM minutieux et pratiquement sans valeur. Les modèles de relation ne sont généralement pas nécessaires!
Sentinel

2
non, les clés étrangères ne sont pas obligatoires pour indiquer "relationnelles"
Silver Moon

Cela n'explique pas vraiment grand-chose.
Nae

29

Je les utilise toujours, mais je crée des bases de données pour les systèmes financiers. La base de données est la partie critique de l'application. Si les données d'une base de données financières ne sont pas totalement exactes, peu importe l'effort que vous consacrez à votre code / conception frontale. Vous perdez juste votre temps.

Il y a aussi le fait que plusieurs systèmes doivent généralement s'interfacer directement avec la base de données - d'autres systèmes qui lisent simplement les données (Crystal Reports) aux systèmes qui insèrent des données (pas nécessairement en utilisant une API que j'ai conçue; elle peut être écrite par un têtu (qui vient de découvrir VBScript et qui a le mot de passe SA pour la boîte SQL). Si la base de données n'est pas aussi idiote qu'elle peut l'être, eh bien - bye bye base de données.

Si vos données sont importantes, alors oui, utilisez des clés étrangères, créez une suite de procédures stockées pour interagir avec les données et créez la base de données la plus robuste possible. Si vos données ne sont pas importantes, pourquoi créez-vous d'abord une base de données?


2
Belle perspicacité. Je dirais que les données sont si importantes pour chaque application qui est réellement utilisée. La seule chose qui diffère est les conséquences des données corrompues. Ils sont élevés pour votre type d'application ...
Jay Godse

20

Mise à jour : j'utilise toujours des clés étrangères maintenant. Ma réponse à l'objection "ils ont compliqué les tests" est "écrivez vos tests unitaires pour qu'ils n'aient pas du tout besoin de la base de données. Tous les tests qui utilisent la base de données devraient l'utiliser correctement, et cela inclut les clés étrangères. Si la configuration est pénible, trouver un moyen moins douloureux de faire la configuration. "


Les clés étrangères compliquent les tests automatisés

Supposons que vous utilisez des clés étrangères. Vous écrivez un test automatisé qui dit "lorsque je mets à jour un compte financier, il devrait enregistrer un enregistrement de la transaction". Dans ce test, vous n'êtes concerné que par deux tableaux: accountset transactions.

Cependant, accountsa une clé étrangère vers contracts, et contractsa un fk vers clients, et clientsa un fk vers cities, et citiesa un fk vers states.

Maintenant, la base de données ne vous permettra pas d'exécuter votre test sans configurer les données dans quatre tables qui ne sont pas liées à votre test .

Il y a au moins deux perspectives possibles à ce sujet:

  • "C'est une bonne chose: votre test doit être réaliste et ces contraintes de données existeront en production."
  • "C'est une mauvaise chose: vous devriez être en mesure de tester des éléments unitaires du système sans impliquer d'autres éléments. Vous pouvez ajouter des tests d'intégration pour le système dans son ensemble."

Il peut également être possible de désactiver temporairement les vérifications de clé étrangère lors de l'exécution des tests. MySQL, au moins, le supporte .


Je me retrouve généralement sur le chemin du milieu ici: j'utilise des FK, puis j'écris des méthodes d'aide de test unitaire qui configurent la base de données pour prendre en charge divers scénarios de test, par exemple une méthode d'aide pour remplir les "villes" et les "états" pour tous les tests qui ont besoin de ces tables remplies.
joelpt

Vous auriez peut-être dû utiliser des tables de liens entre les entités non liées. Ou allez plus loin - DBS séparé: considérez la situation dans une architecture orientée services ou microservice, où chaque élément (clients, comptes, transactions) sont des systèmes différents, avec des bases de données différentes. Pas de FK entre eux comme tous. Dans ce cas, les FK doivent être utilisés pour empêcher les données orphelines dans les sous-tables pour chaque type de données.
JeeBee

3
Il existe également des SGBD qui permettent de différer les contraintes afin qu'elles ne soient vérifiées que lorsque vous validez toute la transaction, donc l'ordre d'insertion, de mise à jour, de suppression n'a pas d'importance
a_horse_with_no_name

2
Si vous testez une mise à jour à partir d'une couche métier, votre environnement de développement doit avoir le FK présent. Lorsque vous mettez à jour votre enregistrement, vous devez disposer des valeurs de colonnes dont vous avez besoin pour que la mise à jour réussisse. Sinon, à mon humble avis, votre test n'est pas valide.
KeyOfJ

3
Votre base de données ne devrait même pas être impliquée dans vos tests unitaires, vous devez vous en moquer. Lors des tests d'intégration, ils seraient impliqués, mais tout problème dû à des clés étrangères est quelque chose que vos utilisateurs rencontreront également à moins que vous ne le répariez.
Andreas Bergström

16

"Ils peuvent rendre la suppression des enregistrements plus lourde - vous ne pouvez pas supprimer l'enregistrement" maître "où il y a des enregistrements dans d'autres tables où les clés étrangères violeraient cette contrainte."

Il est important de se rappeler que la norme SQL définit les actions qui sont prises lorsqu'une clé étrangère est supprimée ou mise à jour. Ceux que je connais sont:

  • ON DELETE RESTRICT- Empêche la suppression de toutes les lignes de l'autre table contenant des clés dans cette colonne. C'est ce que Ken Ray a décrit ci-dessus.
  • ON DELETE CASCADE - Si une ligne de l'autre table est supprimée, supprimez toutes les lignes de cette table qui la référencent.
  • ON DELETE SET DEFAULT - Si une ligne de l'autre table est supprimée, définissez toutes les clés étrangères faisant référence à la valeur par défaut de la colonne.
  • ON DELETE SET NULL - Si une ligne de l'autre table est supprimée, définissez toutes les clés étrangères qui y font référence dans cette table sur null.
  • ON DELETE NO ACTION- Cette clé étrangère indique uniquement qu'il s'agit d'une clé étrangère; à savoir pour une utilisation dans les mappeurs OR.

Ces mêmes actions s'appliquent également à ON UPDATE.

La valeur par défaut semble dépendre de serveur que vous utilisez.


14

@imphasing - c'est exactement le genre de mentalité qui provoque des cauchemars de maintenance.

Pourquoi oh pourquoi ignoreriez-vous l'intégrité référentielle déclarative, où les données peuvent être garanties d'être au moins cohérentes, en faveur de ce que l'on appelle l '"application logicielle", qui est au mieux une faible mesure préventive.


Parce que les développeurs impliqués n'ont jamais abordé un problème qui exige un modèle relationnel non trivial et normalisé. Beaucoup de problèmes ne le font pas, en particulier le genre qui abondent dans la programmation de type web / "médias sociaux" qui fait tout l'engouement aujourd'hui. Si tout ce qui dribble l'arrière d'un framework ORM satisfait le problème en alpha, il est peu probable que quiconque réfléchisse beaucoup plus à la modélisation des données. Beaucoup de ces problèmes sont tout aussi faciles à gérer par les magasins K / V, les bases de données de documents ou la sérialisation d'objets directs.
zxq9

12

Il y a une bonne raison de ne pas les utiliser: si vous ne comprenez pas leur rôle ou comment les utiliser.

Dans de mauvaises situations, les contraintes de clés étrangères peuvent entraîner la réplication des accidents en cascade. Si quelqu'un supprime le mauvais enregistrement, le défaire peut devenir une tâche gigantesque.

En outre, à l'inverse, lorsque vous devez supprimer quelque chose, si elles sont mal conçues, les contraintes peuvent provoquer toutes sortes de verrous qui vous empêchent.


8
La suppression d'une ligne en production sans sauvegarde n'est pas un argument valide. Si vous ne les comprenez pas, vous devriez envisager d'en apprendre davantage au lieu de les omettre.
Guillaume

2
@Guillaume Je pense que sa réponse était un peu sarcastique, à ne pas prendre au pied de la lettre: si vous ne les comprenez pas, alors ne les utilisez pas. Mais bien sûr , vous devez comprendre et à les utiliser.
Benjamin

^ Ça. Ce sont des outils utiles, mais entre les mains d'un novice, ce sont des outils dangereux.
Kent Fredric

11

Il n'y a pas de bonnes raisons de ne pas les utiliser ... à moins que les lignes orphelines ne soient pas un gros problème pour vous, je suppose.


11
Pourquoi les rangées orphelines sont-elles si importantes?
Seun Osewa

2
Et le multithreading? Ils peuvent provoquer un cauchemar multithreading dans certaines situations. Dans une application complexe avec plusieurs threads écrivant la base de données qui peut rencontrer des objets qui doivent se référencer, il est préférable de contrôler l'intégrité référentielle dans la logique métier --- en particulier si les tables vont devenir statiques par la suite.
Keith Pinson

Je suis d'accord. De plus, je préfère avoir des rangées d'ophan que je pourrai récupérer plus tard, plutôt que de les jeter sans pitié.
PedroD

4

La plus grande question est: voudriez-vous conduire avec les yeux bandés? C'est comme ça si vous développez un système sans contraintes référentielles. Gardez à l'esprit que les exigences métier changent, les modifications de conception d'application, les hypothèses logiques respectives dans les changements de code, la logique elle-même peut être refactorisée, etc. En général, les contraintes dans les bases de données sont mises en place sous des hypothèses logiques contemporaines, apparemment correctes pour un ensemble particulier d'assertions et d'hypothèses logiques.

Tout au long du cycle de vie d'une application, les contraintes de référentiel et de vérification des données contrôlent la collecte de données via l'application, en particulier lorsque de nouvelles exigences entraînent des changements d'application logiques.

Au sujet de cette liste - une clé étrangère n'améliore pas en soi les performances ni ne dégrade les performances de manière significative du point de vue du système de traitement des transactions en temps réel. Cependant, il existe un coût agrégé pour la vérification des contraintes dans le système "batch" à volume ÉLEVÉ. Voici donc la différence, en temps réel par rapport au processus de transaction par lots; traitement par lots - où le coût accru, encouru par les contrôles de contraintes, d'un lot traité séquentiellement pose un problème de performance.

Dans un système bien conçu, des contrôles de cohérence des données seraient effectués "avant" le traitement d'un lot (néanmoins, il y a un coût associé ici également); par conséquent, les vérifications des contraintes de clé étrangère ne sont pas requises pendant le temps de chargement. En fait, toutes les contraintes, y compris la clé étrangère, doivent être temporairement désactivées jusqu'à ce que le lot soit traité.

PERFORMANCE DE LA REQUÊTE - si les tables sont jointes sur des clés étrangères, sachez que les colonnes de clés étrangères NE SONT PAS INDEXÉES (bien que la clé primaire respective soit indexée par définition). En indexant une clé étrangère, d'ailleurs, en indexant n'importe quelle clé, et en joignant des tables sur des indexés aide à de meilleures performances, pas en se joignant à une clé non indexée avec une contrainte de clé étrangère.

Changement de sujet , si une base de données ne prend en charge que l'affichage / rendu du contenu / etc du site Web et l'enregistrement des clics, alors une base de données avec des contraintes complètes sur toutes les tables est trop efficace à ces fins. Pensez-y. La plupart des sites Web n'utilisent même pas de base de données pour cela. Pour des exigences similaires, lorsque les données sont simplement enregistrées et non référencées par exemple, utilisez une base de données en mémoire, qui n'a pas de contraintes. Cela ne signifie pas qu'il n'y a pas de modèle de données, oui un modèle logique, mais pas de modèle de données physique.


Eh bien, je ne sais pas pourquoi l'insertion de 3 doubles lignes à la place des blancs et la modification de deux mots comptent comme `` 67% est Jonathan Leffler '', mais je ne pense pas avoir fait quelque chose comme autant de travail dessus. Le texte principal a été fourni par @jay (utilisateur 183837).
Jonathan Leffler

Je viens de supposer que les paragrahps ne fonctionneront pas ici comme c'est le cas dans la plupart des autres sites. Donc, je mets tout cela ensemble, en utilisant des caractères gras pour le changement de flux.
jasbir L

3

Raison supplémentaire d'utiliser des clés étrangères: - Permet une plus grande réutilisation d'une base de données

Raison supplémentaire de NE PAS utiliser de clés étrangères: - Vous essayez de verrouiller un client dans votre outil en réduisant la réutilisation.


3

D'après mon expérience, il est toujours préférable d'éviter d'utiliser des FK dans les applications critiques de base de données. Je ne serais pas en désaccord avec les gars ici qui disent que les FK sont une bonne pratique mais ce n'est pas pratique lorsque la base de données est énorme et a d'énormes opérations CRUD / sec. Je peux partager sans nommer ... l'une des plus grandes banques d'investissement n'a pas un seul FK dans les bases de données. Ces contraintes sont gérées par les programmeurs lors de la création d'applications impliquant DB. La raison fondamentale est que chaque fois qu'un nouveau CRUD est effectué, il doit effectuer plusieurs tables et vérifier pour chaque insertions / mises à jour, bien que ce ne soit pas un gros problème pour les requêtes affectant des lignes uniques, mais cela crée une latence énorme lorsque vous traitez avec traitement par lots que toute grande banque doit effectuer au quotidien.

Il vaut mieux éviter les FK, mais son risque doit être géré par les programmeurs.


8
Je ne pense pas que les pratiques de développement dans les grandes banques établissent la norme d'or.
Adriaan Koster

3

"Avant d'ajouter un enregistrement, vérifiez qu'un enregistrement correspondant existe dans une autre table" est la logique métier.

Voici quelques raisons pour lesquelles vous ne voulez pas cela dans la base de données:

  1. Si les règles métier changent, vous devez changer la base de données. La base de données devra recréer l'index dans de nombreux cas, ce qui est lent sur les grandes tables. (Les règles changeantes incluent: autoriser les invités à publier des messages ou autoriser les utilisateurs à supprimer leur compte malgré la publication de commentaires, etc.).

  2. Changer la base de données n'est pas aussi simple que déployer un correctif logiciel en poussant les modifications vers le référentiel de production. Nous voulons éviter autant que possible de modifier la structure de la base de données. Plus la base de données contient de logique métier, plus vous augmentez les chances de devoir modifier la base de données (et déclencher une réindexation).

  3. TDD. Dans les tests unitaires, vous pouvez remplacer la base de données par des simulations et tester la fonctionnalité. Si vous avez une logique métier dans votre base de données, vous ne faites pas de tests complets et vous devrez soit tester avec la base de données, soit répliquer la logique métier dans le code à des fins de test, dupliquer la logique et augmenter la probabilité que la logique ne fonctionne pas dans le de la même façon.

  4. Réutiliser votre logique avec différentes sources de données. S'il n'y a pas de logique dans la base de données, mon application peut créer des objets à partir des enregistrements de la base de données, les créer à partir d'un service Web, d'un fichier json ou de toute autre source. J'ai juste besoin d'échanger l'implémentation du mappeur de données et je peux utiliser toute ma logique métier avec n'importe quelle source. S'il y a de la logique dans la base de données, cela n'est pas possible et vous devez implémenter la logique au niveau de la couche du mappeur de données ou dans la logique métier. Dans tous les cas, vous avez besoin de ces vérifications dans votre code. S'il n'y a pas de logique dans la base de données, je peux déployer l'application à différents emplacements en utilisant différentes implémentations de base de données ou de fichiers plats.


2

Je suis d'accord avec les réponses précédentes en ce qu'elles sont utiles pour maintenir la cohérence des données. Cependant, il y a quelques semaines, Jeff Atwood a publié un article intéressant sur les avantages et les inconvénients de données normalisées et cohérentes.

En quelques mots, une base de données dénormalisée peut être plus rapide lors du traitement de grandes quantités de données; et vous pouvez ne pas vous soucier de la cohérence précise en fonction de l'application, mais cela vous oblige à être beaucoup plus prudent lorsque vous traitez des données, comme la base de données ne le sera pas.


Jeff fait de bons points. Cependant, Dan Chak dans "Enterprise Rails" montre un moyen de concevoir des tables de cache qui sont essentiellement une copie dénormalisée des données. Les requêtes s'exécutent rapidement et si la table n'a pas besoin d'être actualisée, elle fonctionne bien. Je trouve que si vos données déterminent le comportement (par exemple l'état de l'application) de votre application, vous avez besoin de normaliser autant que possible les données, car sinon des données incohérentes conduisent à un comportement incohérent de l'application.
Jay Godse

Un entrepôt de données dénormalisé peut être utile lors de la lecture de grands volumes de données sur des chemins d'accès cohérents et anticipés . Dans tous les autres scénarios, il s'agit d'une erreur dangereuse.
Peter Wone

2

La base de données Clarify est un exemple de base de données commerciale sans clé primaire ou étrangère.

http://www.geekinterview.com/question_details/18869

Le plus drôle, c'est que la documentation technique va très loin pour expliquer comment les tables sont liées, quelles colonnes utiliser pour les joindre, etc.

En d'autres termes, ils auraient pu rejoindre les tables avec des déclarations explicites (DRI) mais ils ont choisi de ne pas le faire .

Par conséquent, la base de données Clarify est pleine d'incohérences et elle est sous-performante.

Mais je suppose que cela a facilité le travail des développeurs, sans avoir à écrire du code pour gérer l'intégrité référentielle, comme la vérification des lignes associées avant de supprimer, d'ajouter.

Et c'est, je pense, le principal avantage de ne pas avoir de contraintes de clé étrangère dans une base de données relationnelle. Cela facilite le développement, du moins c'est du point de vue du diable.


Le code pour gérer une vérification d'intégrité référentielle ayant échoué est beaucoup plus petit que le code pour gérer les données incohérentes.
Jay Godse

@Jay d'accord! Ne pensez pas que je préconise cette approche.
Ed Guiness

2

Je ne connais que les bases de données Oracle, pas d'autres, et je peux dire que les clés étrangères sont essentielles pour maintenir l'intégrité des données. Avant d'insérer des données, une structure de données doit être créée et corrigée. Lorsque cela est fait - et donc toutes les clés primaires ET étrangères sont créées - le travail est terminé!

Signification: lignes orphelines? Non. Je n'ai jamais vu ça de ma vie. Sauf si un mauvais programmeur a oublié la clé étrangère, ou s'il l'a implémentée à un autre niveau. Les deux sont - dans le contexte d'Oracle - d'énormes erreurs, qui entraîneront une duplication des données, des données orphelines et donc: une corruption des données. Je ne peux pas imaginer une base de données sans FK imposé. Cela ressemble à du chaos pour moi. C'est un peu comme le système d'autorisation Unix: imaginez que tout le monde est root. Pensez au chaos.

Les clés étrangères sont essentielles, tout comme les clés primaires. C'est comme dire: et si on supprimait les clés primaires? Eh bien, le chaos total va se produire. C'est ce que. Vous ne pouvez pas déplacer la responsabilité de clé primaire ou étrangère au niveau de programmation, elle doit être au niveau des données.

Désavantages ? Oui absolument ! Parce qu'à l'insertion, beaucoup plus de contrôles vont se produire. Mais, si l'intégrité des données est plus importante que les performances, c'est une évidence. Le problème avec les performances sur Oracle est plus lié aux index, qui viennent avec PK et FK.


1

Ils peuvent rendre la suppression des enregistrements plus lourde - vous ne pouvez pas supprimer l'enregistrement "maître" où il y a des enregistrements dans d'autres tables où les clés étrangères violeraient cette contrainte. Vous pouvez utiliser des déclencheurs pour effectuer des suppressions en cascade.

Si vous avez mal choisi votre clé primaire, la modification de cette valeur devient encore plus complexe. Par exemple, si j'ai le PK de ma table "clients" comme nom de la personne et que cette clé est un FK dans la table "commandes", si le client veut changer son nom, alors c'est une douleur royale .. . mais c'est juste une conception de base de données de mauvaise qualité.

Je pense que les avantages de l'utilisation des clés Fireign l'emportent sur tous les inconvénients supposés.


5
J'ai tendance à supprimer rarement les choses de toute façon. Il suffit de marquer comme ayant un bit "Visible / actif".
Dana

+1 pour "Je crois que les avantages de l'utilisation des clés Fireign l'emportent sur tous les inconvénients supposés"
Ian Boyd

2
Vous ne changez jamais, jamais la valeur d'une clé primaire. Vous supprimez la ligne entière et la recréez différemment. Si vous pensez que vous devez le changer , votre schéma est défectueux.
DanMan

Changer le nom du client ne serait pas du tout compliqué SI votre clé étrangère est définie sur le CustomerId (PK). dans le tableau des commandes. La seule façon dont cela serait gênant est que le FK soit défini sur CustomerName, ce qui ne devrait jamais être le cas. IMHO
KeyOfJ

1

La vérification des contraintes de clé étrangère prend un certain temps CPU, donc certaines personnes omettent les clés étrangères pour obtenir des performances supplémentaires.


6
Combien de temps processeur est consacré à la suppression des données en double et incohérentes?
Ed Guiness

Ouais, c'est vrai. Sur un système sur lequel je travaille, nous devons insérer 10 à 40 Go de données à la fois dans une base de données et les performances FK avec et sans sont visibles dans le temps total nécessaire.
Paul Mendoza

1

J'ai également entendu cet argument - de personnes qui ont oublié de mettre un index sur leurs clés étrangères et se sont ensuite plaintes que certaines opérations étaient lentes (car la vérification des contraintes pouvait profiter de n'importe quel index). Donc, pour résumer: il n'y a aucune bonne raison de ne pas utiliser de clés étrangères. Toutes les bases de données modernes prennent en charge les suppressions en cascade, donc ...


9
Je crois que la vraie raison pour laquelle les contraintes FK ne sont pas utilisées par certains (la plupart, de mon point de vue) est la pure paresse sous prétexte qu'ils peuvent défendre leur paresse avec leur argument d'économie de performance. Je crois fermement que la grande majorité des dépenses de stupidité encourues par notre entreprise est due au manque d'application des contraintes FK et à l'effet d'entraînement que cela a sur une entreprise. Le manque de clés uniques est l'autre chose qui me rend fou à côté de plus de 2000 procédures stockées en ligne avec 12 niveaux de FI imbriqués et une mise en retrait aléatoire, mais je m'arrête maintenant.
Tchad

1

L'argument que j'ai entendu est que le front-end devrait avoir ces règles commerciales. Les clés étrangères "ajoutent une surcharge inutile" alors que vous ne devriez pas autoriser les insertions qui rompent vos contraintes en premier lieu. Suis-je d'accord avec cela? Non, mais c'est ce que j'ai toujours entendu.

EDIT: Je suppose qu'il faisait référence aux contraintes de clé étrangère , pas aux clés étrangères en tant que concept.


Nan. Il n'aime pas les vraies clés!
ljs

Cela m'étonne. Il y a une grande différence entre ne pas aimer les contraintes de clé étrangère et ne pas aimer les clés étrangères. Je ne sais pas comment vous avez une base de données relationnelle sans eux.
lordscarlet

Oui, j'ai été choqué quand je l'ai entendu. Il aurait cependant pu être involontairement ironique; peut-être qu'il
postera

1

Pour moi, si vous voulez respecter les normes ACID , il est essentiel d'avoir des clés étrangères pour assurer l'intégrité référentielle.


1

Je dois appuyer la plupart des commentaires ici, les clés étrangères sont des éléments nécessaires pour garantir que vous avez des données avec intégrité. Les différentes options pour ON DELETE et ON UPDATE vous permettront de contourner certaines des «chutes» que les gens mentionnent ici concernant leur utilisation.

Je trouve que dans 99% de tous mes projets, je disposerai de FK pour faire respecter l'intégrité des données, cependant, il y a de rares occasions où j'ai des clients qui DOIVENT conserver leurs anciennes données, quelle que soit leur gravité ... mais ensuite je passe beaucoup de temps à écrire du code qui n'entre de toute façon que pour obtenir les données valides, donc cela devient inutile.


1

Qu'en est-il de la maintenabilité et de la constance à travers les cycles de vie des applications? La plupart des données ont une durée de vie plus longue que les applications qui les utilisent. Les relations et l'intégrité des données sont beaucoup trop importantes pour laisser espérer que la prochaine équipe de développement réussira dans le code de l'application. Si vous n'avez pas travaillé sur une base de données avec des données sales qui ne respectent pas les relations naturelles, vous le ferez. L'importance de l'intégrité des données deviendra alors très claire.


1

Je pense également que les clés étrangères sont une nécessité dans la plupart des bases de données. Le seul inconvénient (en plus du résultat de performance associé à la cohérence forcée) est que le fait d'avoir une clé étrangère permet aux gens d'écrire du code qui suppose qu'il existe une clé étrangère fonctionnelle. Cela ne devrait jamais être autorisé.

Par exemple, j'ai vu des gens écrire du code qui s'insère dans la table référencée, puis tente d'insérer dans la table de référence sans vérifier que la première insertion a réussi. Si la clé étrangère est supprimée ultérieurement, cela se traduit par une base de données incohérente.

Vous n'avez pas non plus la possibilité d'assumer un comportement spécifique lors de la mise à jour ou de la suppression. Vous devez toujours écrire votre code pour faire ce que vous voulez, qu'il y ait ou non une clé étrangère. Si vous supposez que les suppressions sont en cascade alors qu'elles ne le sont pas, vos suppressions échoueront. Si vous supposez que les mises à jour des colonnes référencées sont propagées aux lignes de référence lorsqu'elles ne le sont pas, vos mises à jour échoueront. Pour écrire du code, vous pourriez aussi bien ne pas avoir ces fonctionnalités.

Si ces fonctionnalités sont activées, votre code les émulera de toute façon et vous perdrez un peu de performances.

Donc, le résumé .... Les clés étrangères sont essentielles si vous avez besoin d'une base de données cohérente. Les clés étrangères ne doivent jamais être supposées être présentes ou fonctionnelles dans le code que vous écrivez.


1

Je fais écho à la réponse de Dmitriy - très bien mise.

Pour ceux qui s'inquiètent des surcharges de performances que les FK apportent souvent, il existe un moyen (dans Oracle) d'obtenir l'avantage d'optimiseur de requêtes de la contrainte FK sans les coûts de validation des contraintes lors de l'insertion, de la suppression ou de la mise à jour. Il s'agit de créer la contrainte FK avec les attributs RELY DISABLE NOVALIDATE. Cela signifie que l'optimiseur de requêtes suppose que la contrainte a été appliquée lors de la génération des requêtes, sans que la base de données applique réellement la contrainte. Vous devez être très prudent ici pour prendre la responsabilité lorsque vous remplissez une table avec une contrainte FK comme celle-ci pour vous assurer absolument que vous n'avez pas de données dans vos colonnes FK qui violent la contrainte, comme si vous le faites, vous pourrait obtenir des résultats peu fiables à partir de requêtes impliquant la table sur laquelle cette contrainte FK est activée.

J'utilise généralement cette stratégie sur certaines tables de mon schéma de magasin de données, mais pas dans mon schéma de transfert intégré. Je m'assure que les tables à partir desquelles je copie des données ont déjà la même contrainte appliquée, ou que la routine ETL applique la contrainte.


1

Beaucoup de personnes répondant ici sont trop accrochées à l'importance de l'intégrité référentielle implémentée via des contraintes référentielles. Travailler sur de grandes bases de données avec intégrité référentielle ne fonctionne tout simplement pas bien. Oracle semble particulièrement mauvais pour les suppressions en cascade. Ma règle générale est que les applications ne doivent jamais mettre à jour la base de données directement et doivent se faire via une procédure stockée. Cela conserve la base de code à l'intérieur de la base de données et signifie que la base de données conserve son intégrité.

Lorsque de nombreuses applications peuvent accéder à la base de données, des problèmes surviennent en raison de contraintes d'intégrité référentielle, mais cela est dû à un contrôle.

Il y a aussi un problème plus large en ce sens que les développeurs d'applications peuvent avoir des exigences très différentes que les développeurs de bases de données ne connaissent pas nécessairement.


5
"Les applications ne doivent jamais mettre à jour la base de données directement et doivent se faire via une procédure stockée. Cela conserve la base de code à l'intérieur de la base de données et signifie que la base de données conserve son intégrité." <- On suppose ici que la logique des procédures stockées ne peut pas violer l'intégrité des données, ce qui est tout simplement faux.
Tim Gautier

1

Si vous êtes absolument sûr que le système de base de données sous-jacent ne changera pas à l'avenir, j'utiliserais des clés étrangères pour garantir l'intégrité des données.

Mais voici une autre très bonne raison concrète de ne pas utiliser du tout de clés étrangères:

Vous développez un produit qui devrait prendre en charge différents systèmes de base de données.

Si vous travaillez avec Entity Framework, qui est capable de se connecter à de nombreux systèmes de base de données différents, vous pouvez également prendre en charge les bases de données sans serveur "open-source-free-of-charge". Toutes ces bases de données peuvent ne pas prendre en charge vos règles de clé étrangère (mise à jour, suppression de lignes ...).

Cela peut entraîner différents problèmes:

1.) Vous pouvez rencontrer des erreurs lorsque la structure de la base de données est créée ou mise à jour. Peut-être qu'il n'y aura que des erreurs silencieuses, car vos clés étrangères sont simplement ignorées par le système de base de données.

2.) Si vous comptez sur des clés étrangères, vous effectuerez de manière appropriée, voire aucune vérification de l'intégrité des données dans votre logique métier. Maintenant, si le nouveau système de base de données ne prend pas en charge ces règles de clé étrangère ou se comporte simplement d'une manière différente, vous devez réécrire votre logique métier.

Vous pouvez vous demander: qui a besoin de différents systèmes de base de données? Eh bien, tout le monde ne peut pas se permettre ou veut un SQL-Server complet sur sa machine. Il s'agit d'un logiciel qui doit être maintenu. D'autres ont déjà investi du temps et de l'argent dans un autre système DB. La base de données sans serveur est idéale pour les petits clients sur une seule machine.

Personne ne sait comment se comportent tous ces systèmes de base de données, mais votre logique métier, avec les contrôles d'intégrité, reste toujours la même.


0

J'ai toujours pensé que c'était paresseux de ne pas les utiliser. On m'a appris que cela devrait toujours être fait. Mais ensuite, je n'ai pas écouté la discussion de Joel. Il avait peut-être une bonne raison, je ne sais pas.


C'était plus une remarque spontanée qu'une discussion, bien que je devrais peut-être rechercher précisément ce qu'il pense du sujet indépendamment! Mais j'étais également curieux de connaître l'opinion de la communauté sur ce sujet!
ljs

0

Une fois qu'un FK peut vous poser un problème, c'est lorsque vous avez des données historiques qui font référence à la clé (dans une table de recherche) même si vous ne voulez plus que la clé soit disponible.
De toute évidence, la solution consiste à mieux concevoir les choses à l'avance, mais je pense à des situations réelles ici où vous n'avez pas toujours le contrôle de la solution complète.
Par exemple: vous avez peut-être une table de recherche customer_typequi répertorie différents types de clients - disons que vous devez supprimer un certain type de client, mais (en raison de contraintes commerciales) ne sont pas en mesure de mettre à jour le logiciel client, et personne n'a invisited cette situation lors du développement du logiciel, le fait qu'il s'agisse d'une clé étrangère dans une autre table peut vous empêcher de supprimer la ligne même si vous connaissez les données historiques qui y font référence, elles ne sont pas pertinentes.
Après avoir été brûlé avec cela plusieurs fois, vous vous éloignez probablement de l'application des relations avec les bases de données.
(Je ne dis pas que c'est bon - je donne juste une raison pour laquelle vous pouvez décider d'éviter les contraintes FK et db en général)


Si je comprends ce que vous essayez de dire, je pense que ma réponse serait de supprimer logiquement l'enregistrement dans la table de recherche ou d'archiver les données historiques qui ne sont plus pertinentes et d'archiver également l'enregistrement de recherche.
Chad
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.