web-dev-qa-db-fra.com

Intégrité relationnelle sans relations

J'ai environ 15 ans d'expérience en génie logiciel, écrivant des logiciels d'entreprise avec des bases de données relationnelles. Principalement SQL Server et Oracle. J'ai toujours été d'avis que vous devriez définir des relations dans votre base de données et laisser votre base de données gérer l'intégrité relationnelle. Et dans mon cas, 99,9% du temps, j'utilise une colonne d'identité unique comme clé primaire.

Maintenant que mon opinion est hors de portée, j'aimerais avoir des conseils sur une application que nous avons au travail. Il s'agit d'une application tierce avec laquelle mon application doit s'interfacer. Les deux applications utilisent SQL Server comme base de données. Ils n'ont pas d'interface pour envoyer et récupérer des données. Pour cette raison, ils m'ont donné des parties de leur schéma de base de données et des descriptions sur la façon d'enregistrer les données avec des requêtes SQL.

Il était clair d'après le schéma qui m'a été envoyé qu'ils n'utilisaient pas de relations ni n'utilisaient de valeurs d'identité pour les clés primaires dans la plupart des cas. En suivant les communications avec eux, ils ont à peu près dit que les colonnes d'identité sont l'exception, pas la norme. Ils ont également déclaré qu'ils gèrent toute l'intégrité référentielle dans leur code.

Je suis à peu près convaincu qu'ils ont commis une horrible erreur. Par exemple, je dois enregistrer des données dans cette base de données et je n'ai aucun de leur "code d'intégrité référentielle" dans mon application. Et si quelqu'un devait exécuter certaines requêtes directement dans la base de données, cela pose également un problème. Je pense que c'est un cauchemar de maintenance.

Quelqu'un peut-il présenter des arguments raisonnables pour étayer objectivement la décision prise par ce fournisseur? J'ai du mal à trouver une bonne raison.

6
Dan

Les raisons de ces décisions de conception ne sont souvent pas techniques, mais organisationnelles. J'ai vu cela se produire dans le monde réel, dans des situations du genre suivant:

  • Au moment où le système est conçu, il n'y a qu'une seule application qui a un accès exclusif à la base de données, donc les contraintes référentielles et les colonnes d'ID ne sont pas si importantes au début.

  • Les développeurs du système sont bien formés au développement d'applications, mais moins formés à la conception de bases de données.

  • Les concepteurs peuvent avoir eu de mauvaises expériences avec les contraintes d'intégrité référentielle dans la base de données, car ils ne permettent généralement pas facilement d'implémenter des "exceptions dans des cas spéciaux" - ces exceptions sont beaucoup plus faciles à gérer du côté de l'application.

    Par exemple: "cette colonne du tableau A doit être une clé étrangère non nulle réf. À la colonne ID du tableau B" - puis quelqu'un dit "oh, sauf lorsque la colonne isTemplate du tableau A est true. Pour résoudre ce type d'exigences côté DB, il faudrait remplacer la contrainte FK par un déclencheur DB plus ou moins complexe.

  • L'approche - normalement très bonne - de "commençons par une solution de travail la plus simple d'abord et améliorons plus tard" est interprétée comme commençons d'abord sans relations dans la base de données et ajoutons-les plus tard = (au lieu de commençons par des contraintes strictes et rendons-les moins strictes plus tard).

Malheureusement, une fois qu'un système est construit sans intégrité référentielle et que sa première version entre en production, tôt ou tard, il contiendra beaucoup de données qui n'auraient pas pu être insérées dans la base de données avec certaines contraintes sensibles activées.

Ensuite, il devient difficile d'ajouter ces contraintes à la base de données par la suite. Il est souvent plus facile pour les développeurs de modifier l'application à la place pour la faire gérer ces données de "faible qualité", de sorte que les données peuvent rester non modifiées dans la base de données, au lieu de lancer un "processus d'amélioration des données", qui serait nécessaire pour corriger le problème. problèmes au niveau de la base de données, mais peuvent nécessiter une assistance par les utilisateurs et les administrateurs.

Bien sûr, lorsqu'un système se développe et qu'il est étendu pour que plus d'une application accède à la base de données, en particulier plus d'une qui y écrit des données, il y a sûrement un point où il serait préférable d'avoir une conception de la base de données plus rigide. . Mais plus on essaie d'y arriver, plus c'est difficile.

12
Doc Brown

C'est une tendance que je constate de plus en plus dans de nombreuses industries - une structure de données plus plate qui est beaucoup plus optimiste quant à la redondance des données.

Peut-être ne devrions-nous pas être trop surpris à ce sujet étant donné:

  • Le stockage est bon marché, les processeurs sont rapides et la mémoire est abondante, ce qui signifie que la redondance des données est beaucoup moins un problème de performances
  • L'essor de LINQ dans les langages .NET signifie que le découpage et le découpage des données sont beaucoup plus faciles du côté client
  • La nature plus détendue des langues modernes au dogme établi du passé, par ex. (du Zen de Python) Flat is better than nested

J'aurais été d'accord avec les points de la réponse de Doc Brown dans leur intégralité il y a environ cinq ans, mais ce n'est vraiment qu'une petite partie. Beaucoup de choses ont changé depuis lors, tant dans le développement de logiciels que dans les arènes de bases de données.

Je me souviens d'un reportage il y a quelques années où la structure de base de données non relationnelle de Facebook a été mentionnée à un gourou du monde du SGBDR qui se moquait: "Cela ne fonctionnera jamais et ne se développera jamais". Comme nous l'avons vu depuis - il l'a fait et il le fait.

2
Robbie Dee

Je saute souvent l'intégrité référentielle dans la DB, c'est-à-dire les contraintes FK

Mais j'ai toujours des PK uniques.

Donc, dans mon cas, c'est plus comme un manque de relations strictes dans l'ensemble. Bien sûr, vous pouvez avoir une adresse client sans client - assommez-vous. Tout fonctionnera sauf les bits qui ne fonctionnent pas.

De plus, je cache la base de données derrière une API pour que toutes les relations qui doivent être appliquées puissent être appliquées.

Cela fonctionne bien avec des données distribuées où la contrainte ne peut en aucun cas être appliquée de manière atomique et vous devez faire face à une erreur potentielle.

Votre fournisseur est allé plus loin en ne disposant pas d'ID, mais soyons généreux et supposons qu'il existe des clés composites uniques. En théorie, cela fonctionne aussi bien.

Mais ils vous permettent également d'accéder directement en contournant une API. Même s'ils avaient des contraintes strictes au niveau de la base de données, cela reste suspect. Vous ne pouvez pas appliquer toutes les règles de la base de données, vous serez donc en mesure de la casser si vous essayez vraiment.

Si c'est le manque d'API qui est le péché cardinal dans ce cas, je pense que vous devez vous mettre sous la loupe pour demander cet accès de bas niveau à des logiciels tiers.

Plutôt que d'être intrinsèquement mauvais Il semble que ce logiciel manque simplement des fonctionnalités dont vous avez besoin.

1
Ewan

Quel est le vrai problème?

Le vrai problème ici, ce n'est pas l'absence d'intégrité référentielle et d'autres contraintes critiques: c'est le fait que la base de données est utilisée comme support d'interface sans assurer une validation correcte des données envoyées à l'application.

Tôt ou tard, cela conduira à des incohérences:

  • Les contraintes de base de données pourraient aider à éviter une telle situation en garantissant un minimum de cohérence lorsque les données sont ajoutées.
  • Une meilleure approche serait l'application pour offrir une interface (par exemple, basée sur une API ou un fichier) pour acquérir les données et les désinfecter avant de les utiliser.

Y a-t-il des arguments historiques qui expliquent l'absence d'intégrité référentielle?

Tout d'abord, je dois admettre que je partage totalement vos opinions. L'intégrité référentielle renforcera non seulement la fiabilité des données, mais elle fournira en outre des informations supplémentaires à l'optimiseur pour faire son travail.

Cela étant dit, les équipes peuvent être induites en erreur par des arguments historiques contre l'intégrité référentielle:

  • J'ai commencé à développer avec Oracle 5 en 1986, à cette époque il y avait un schéma de verrouillage de table pour toute mise à jour. Il n'y avait aucune intégrité référentielle avant 1992 avec Oracle 7.
  • Pendant un certain temps, l'intégrité référentielle a été implémentée dans un couple de SGBD au détriment des performances (je me souviens par exemple d'un cas où des verrous supplémentaires sur des clés étrangères réduisaient la concurrence).
  • Colonnes numérotées automatiquement où les extensions spécifiques au fournisseur avant de devenir norme SQL en 20 . Cela a rendu l'utilisation des colonnes d'identification délicate (par exemple, requête, mise à jour, échec, nouvelle tentative). Par conséquent, les touches naturelles (significatives) ont été préférées lorsque cela était possible. Par exemple, l'ID de commande était presque toujours géré comme un ID unique, mais les éléments de ligne de commande avaient rarement leur propre ID unique, mais un ID combiné (l'ID de commande + le numéro de ligne était préféré car plus simple à mettre en œuvre). Ou vous aviez un identifiant de périphérique combiné + horodatage au lieu d'un identifiant unique pour chaque mesure enregistrée par le périphérique. Pourquoi est-ce important? Parce que dans un tel contexte, l'utilisation de l'intégrité référentielle a rendu le changement de clés naturelles très difficile (à moins que votre base de données ne prenne en charge les changements en cascade).

Donc, la question n'est pas AS400 ou non, mais une expérience antérieure faite dans les temps anciens

Y a-t-il encore des raisons valables de ne pas avoir l'intégrité référentielle?

Ces raisons historiques ne doivent pas faire penser que l'absence d'intégrité référentielle serait un signe de pratique obsolète!

Plusieurs raisons valables pour ne pas utiliser l'intégrité référentielle:

  • Indépendance des bases de données: bases de données orientées documents (MongoDB etc ...) ne prévoient pas l'intégrité référentielle, car elles privilégient les ensembles de données moins structurés. Donc, si vous développez des applications qui ont l'intention d'utiliser un tel SGBD ou qui souhaitent garantir l'indépendance de la base de données, vous devrez vous soucier de l'intégrité de votre application. Vous ne vous soucierez donc pas vraiment du niveau DB.
  • DDD et objets de valeur: les objets de valeur diffèrent des entités en ce qu'ils n'ont pas d'identité. Un objet valeur est uniquement identifié par la valeur de ses attributs. Traduit en SQL, cela signifie que vous n'utilisez pas un ID unique pour identifier l'objet de valeur. L'intégrité référentielle est alors moins évidente, de sorte que vous commencerez sans.
1
Christophe