web-dev-qa-db-fra.com

Ne pas utiliser de contraintes de clé étrangère dans la pratique. Est-ce que c'est bon?

Ne pas utiliser les contraintes FK est la règle incalculable de mon entreprise. Les contraintes FK sont utilisées uniquement lors de la conception d'ERD et ne sont pas utilisées lors de la création de tables.

Selon mon aîné, dans la pratique, ce sont des obstacles qui prennent beaucoup de temps lorsque nous traitons des questions urgentes. Il dit que lorsque nous devons utiliser des instructions INSERT/UPDATE/DELETE immédiatement, les contraintes bloquent ces instructions à exécuter et l'écriture d'instructions tout en conservant les contraintes prend également du temps. J'ai même entendu dire que de nombreuses autres entreprises le faisaient.

Bien que je comprenne un peu les difficultés, je ne suis pas sûr que ce soit un bon moyen car c'est tout à fait contraire à ma compréhension de DB. Cette entreprise est aussi mon premier emploi, donc je ne sais pas comment les autres entreprises y font face.

Concrètement, qu'en pensez-vous? Cela peut-il être justifié? Y a-t-il de meilleures façons? Que font les autres entreprises à ce sujet?

MISE À JOUR: Il semble que ce soit une approche assez courante pour les entreprises sud-coréennes. J'ai demandé à quelques autres seniors qui travaillaient pour d'autres entreprises, et la plupart d'entre eux disent qu'ils font tous comme ça. Et même l'un d'eux a travaillé pour une société financière! Intéressant...

11
user2652379

Rien n'est gratuit. Parfois, ne pas avoir quelque chose n'est pas gratuit non plus. Avoir et ne pas avoir déclaré de clés étrangères entraîne des coûts et des avantages.

Le point d'une clé étrangère (FK) est de s'assurer que la colonne this ici ne peut avoir que des valeurs provenant de la colonne that là-bas1. De cette façon, nous pouvons être sûrs de ne capturer que les commandes des clients qui existent réellement, des produits que nous produisons et vendons. Beaucoup de gens pensent que c'est une bonne idée.

La raison pour laquelle nous les déclarons dans le SGBD est afin qu'il puisse prendre soin de les appliquer. Il n'autorisera jamais aucune donnée enfreignant les règles. De plus, cela ne vous permettra jamais de vous débarrasser des données nécessaires à l'application des règles. En déléguant cette tâche à la machine, nous pouvons avoir confiance en l'intégrité des données, quelle que soit leur source ou quand elles ont été écrites ou par quelle application elles sont passées. Bien sûr, cela a un coût. Le SGBD doit vérifier les règles sont suivies, pour chaque ligne, pour chaque requête, tout le temps. Cela prend du temps et des efforts, ce qui représente une charge pour le serveur. Il exige également que les humains soumettent le DML dans une séquence qui respecte les règles. Plus de forcer sournoisement dans un ordre, puis de rattraper l'administrateur par la suite. Oh non méchant humain, vous devez d'abord créer le client, puis le produit (et toutes les lignes prérequises) et seulement alors vous pouvez créer une commande.

Sans clés étrangères, nous sommes beaucoup plus libres de ce que nous pouvons faire et de l'ordre dans lequel nous pouvons le faire. Les lignes problématiques peuvent être supprimées ad hoc pour permettre aux processus critiques de se terminer. Les données peuvent être corrigées par la suite, lorsque la panique est terminée. Les INSERT sont généralement un peu plus rapides (ce qui s'additionne au fil du temps) car aucune vérification des FK n'est effectuée. Des sous-ensembles arbitraires de données peuvent être extraits de la base de données comme vous le souhaitez sans avoir à vous assurer que toutes les données de prise en charge sont incluses. Etc. Cela peut être tout à fait correct si les personnes impliquées connaissent le système, prennent des notes attentives, ont de bonnes routines de réconciliation, comprennent les conséquences et ont le temps de s'organiser après elles-mêmes. Le coût est que quelque chose, quelque part, est raté une fois et la base de données se détériore en ordure à peine crédible.

Certaines équipes mettent les chèques dans l'application plutôt que dans la base de données. Encore une fois, cela peut fonctionner. Il me semble, cependant, que la charge totale du serveur sera sensiblement la même (ou légèrement plus élevée) avec cette approche, mais le risque d'oublier une vérification dans un peu de code quelque part est beaucoup plus élevé. Avec DRI, la règle est communiquée à l'ordinateur une fois et est appliquée pour toujours. Dans le code d'application, il doit être réécrit avec chaque nouveau programme.

Pour mes deux cents, je suis tout à fait pour les clés étrangères. Laissez les ordinateurs faire ce qu'ils font, comme la vérification répétitive de routine de la correspondance des valeurs de colonne. Nous, les humains, pouvons nous concentrer à imaginer de nouvelles choses intéressantes. Ayant pris la responsabilité d'un système il y a quelques mois, j'ajoute des FK à la plupart des tables. Il y en a cependant quelques-uns où je ne les ajouterai pas. C'est là que nous recueillons des données de sources externes. Le coût du rejet de ces lignes est supérieur au coût de l'acceptation de mauvaises données et de leur correction ultérieure. Donc, pour ces quelques tables, il n'y aura pas de clés étrangères. Je le fais avec les yeux ouverts, sachant que des procédures de surveillance et de correction sont en place.

1Je reconnais l'existence de contraintes de clé étrangère multi-colonnes.

22
Michael Green

Votre aîné a horriblement tort. Les contraintes FK sont une ligne de code pour garantir l'intégrité des données. Ce qui prend plus de temps,

  • littéralement une ligne de code dans un langage déclaratif, et parfois moins car vous pouvez ajouter des clés étrangères en ligne lorsque vous CREATE la table.
  • ou, pour assumer l'intégrité et gérer les inconvénients des hypothèses qui ont échoué.

Il n'y a aucune raison pas d'utiliser des contraintes de clé étrangère et d'utiliser une base de données relationnelle. Vous avez deux tâches en tant que DBA SQL:

  • Créez un schéma avec DDL.
  • Accéder au schéma avec DML.

Si vous n'assurez pas l'intégrité de vos données avec le schéma, vous sautez simplement une partie du travail. La nature même d'une transaction est d'assurer un atomic tout ou rien. Vous souhaitez définir "tous" sans utiliser de contraintes de clé étrangère? C'est un pita.

CREATE TABLE foo ( int a PRIMARY KEY );
CREATE TABLE bar ( int b REFERENCES foo );
CREATE TABLE baz ( int b );

Faites maintenant une transaction atomique pour bar et baz

  1. insère dans foo.a la valeur (1). Échoue si la valeur existe.
  2. insère dans une autre table (bar.b ou baz.b) la même valeur, 1 et échoue si la valeur n'existe pas dans foo.a.

Lequel vous fait gagner du temps?

5
Evan Carroll

Il est presque toujours préférable de déclarer des contraintes de clé étrangère que d'utiliser des clés étrangères sans contrainte dans le SGBD. La contrainte de clé étrangère maintient l'intégrité référentielle, ce qui empêche une forme de corruption de données.

L'alternative consistant à appliquer l'intégrité référentielle au niveau de l'application coûte presque toujours autant ou plus en ressources informatiques et en efforts de programmation que le serait la contrainte du SGBD.

L'alternative de ne pas maintenir l'intégrité référentielle conduit généralement à des données corrompues et à des résultats peu fiables.

Il y a de fortes chances que la politique de votre site se soit trompée dès le départ. Il y a des exceptions à cela, mais elles sont rares.

2
Walter Mitty

C'est quelque chose qui devrait vraiment être testé pour votre propre situation, mais pour fournir l'intégrité des données des clés étrangères tout en supprimant ou mettant à jour rapidement les données que vous pourriez examiner en cascade.

CREATE TABLE ChildTable (
    id INT NOT NULL IDENTITY(1,1), 
    parent_id INT,
    FOREIGN KEY (parent_id)
        REFERENCES parent(id)
        ON DELETE CASCADE
);
2
MrTCS