D'après mon expérience, de nombreux projets que j'ai lus dans le passé ne contenaient pas de définition de relation dans la base de données, ils ne les définissaient que dans le code source. Je me demande donc quels sont les avantages / inconvénients de la définition des relations entre les tables de la base de données et du code source? Et la question plus générale concerne d’autres fonctionnalités avancées des bases de données modernes telles que la cascade, les déclencheurs, les procédures… Il ya quelques points dans mes pensées:
Dans la base de données:
Corrigez les données de la conception. Prévenez les erreurs d'application pouvant générer des données non valides.
Réduisez l'aller-retour réseau vers l'application lors de l'insertion / de la mise à jour de données, car l'application doit effectuer davantage de requêtes pour vérifier l'intégrité des données.
En code source:
Plus flexible.
Il est préférable d’effectuer une mise à l’échelle sur plusieurs bases de données, car la relation peut parfois être cross-database.
Plus de contrôle sur l'intégrité des données. La base de données n'a pas à vérifier chaque fois que l'application modifie des données (la complexité peut être O (n) ou O (n log n) (?)). Au lieu de cela, il est délégué à l'application. Et je pense que la gestion de l'intégrité des données dans l'application entraînera plus de messages d'erreur détaillés que l'utilisation de la base de données. Exemple: lorsque vous créez un serveur d'API, si vous définissez les relations dans la base de données et que quelque chose ne va pas (l'entité référencée n'existe pas), vous obtiendrez une exception SQL avec un message. Le moyen le plus simple consiste à renvoyer 500 informations au client en signalant une "erreur de serveur interne" et le client n’a aucune idée de ce qui ne va pas. Ou le serveur peut analyser le message pour déterminer ce qui ne va pas, ce qui est une manière laide et sujette aux erreurs, à mon avis. Si vous laissez l'application gérer cela,
Y a-t-il autre chose?
Edit: comme le fait remarquer Kilian, mon point sur les performances et l’intégrité des données est très erroné. Donc j'ai édité pour corriger mon point là. Je comprends tout à fait que laisser la base de données la gérer sera une approche plus efficace et robuste. S'il vous plaît vérifier la question mise à jour et donner quelques idées à ce sujet.
Edit: merci à tous. Les réponses que j'ai reçues indiquent toutes que les contraintes / relations doivent être définies dans la base de données. :) J'ai une autre question, car elle est tout à fait hors de portée de cette question. Je viens de l'afficher sous la forme d'une question distincte: Gestion des erreurs de base de données pour le serveur d'API . S'il vous plaît laissez quelques idées.
Réponses:
TL; DR: les contraintes de relation doivent figurer dans la base de données.
Votre application n'est pas assez grosse.
Vous avez raison de dire que l’application de relations entre bases de données peut nécessiter leur application dans l’application.
Je tiens toutefois à souligner que vous devez d’abord consulter la documentation du logiciel de base de données que vous utilisez, puis consulter les offres de produits existants. Par exemple, il existe des offres de regroupement en plus de Postgres et de MySQL.
Et même si vous avez besoin d' une validation dans l'application, ne jetez pas le bébé avec l'eau du bain . Après tout, moins vous avez à faire, mieux vous vous portez.
Enfin, si vous vous inquiétez des problèmes d'évolutivité futurs, je crains que votre application ne soit soumise à des modifications importantes avant de pouvoir de toute façon évoluer. En règle générale, chaque fois que vous développez 10x, vous devez repenser la conception ... ne perdez donc pas trop d'argent pour ne pas anticiper les problèmes d'évolutivité, mais utilisez plutôt l'argent pour atteindre le point où vous en êtes confronté.
Votre application n'est pas assez correcte.
Quelle est la probabilité que la base de données que vous utilisez ait une implémentation incorrecte du contrôle par rapport à la probabilité que votre application ait une implémentation incorrecte du contrôle?
Et lequel modifiez-vous le plus souvent?
Je parie que la base de données est correcte, à tout moment .
Vos développeurs ne pensent pas assez distribués.
Drapeau rouge ! 1
Si vous pensez:
alors vous avez échoué au problème le plus élémentaire de la simultanéité: un autre processus / fil pourrait ajouter l'enregistrement au fur et à mesure.
Si vous pensez:
alors vous avez échoué à prendre en compte MVCC: la vue de la base de données que vous avez est un instantané au moment où votre transaction a commencé; il ne montre pas toutes les mises à jour en cours et peut-être même pas validées.
Le maintien des contraintes sur plusieurs sessions est un problème très difficile, soyez heureux qu'il soit résolu dans votre base de données.
1 Sauf si votre base de données implémente correctement la propriété Serializable; mais peu le font réellement.
Dernier:
Ne pas analyser les messages d'erreur . Si vous utilisez une base de données de type production, les erreurs structurées doivent être renvoyées. Vous aurez au moins un code d'erreur pour indiquer ce qui peut ne pas être correct. Sur la base de ce code, vous pouvez créer un message d'erreur approprié.
Notez que la plupart du temps, le code est suffisant: si vous avez un code d'erreur indiquant qu'une clé étrangère référencée n'existe pas, il est probable que cette table ne comporte qu'une seule clé étrangère. Vous savez donc dans le code quel est le problème. .
En outre, et soyons honnêtes ici, la plupart du temps, vous ne gérerez pas les erreurs de façon aussi élégante. Tout simplement parce qu'ils sont nombreux et que vous ne pourrez pas en rendre compte pour tous ...
... qui rejoint juste le point correct ci-dessus. Chaque fois que vous voyez une "500: Internal Server Error" parce qu'une contrainte de base de données s'est déclenchée et qu'elle n'a pas été gérée, cela signifie que la base de données vous a sauvegardé, car vous avez simplement oublié de la gérer dans le code.
la source
C'est un point profondément erroné. Les bases de données ont été créées précisément dans ce but. Si vous avez besoin de contrôles d'intégrité des données (et si vous pensez ne pas en avoir besoin, vous vous trompez probablement), laisser la base de données les gérer est certainement plus efficace et moins sujet aux erreurs que de le faire dans la logique d'application.
la source
Les contraintes doivent se trouver dans votre base de données, car (avec la meilleure volonté du monde), votre application ne sera pas la seule chose à accéder à cette base de données.
À un moment donné, il faudra peut-être installer un correctif scripté dans la base de données ou migrer des données d'une table à une autre lors du déploiement.
De plus, vous pouvez avoir d’autres exigences, par exemple "Le gros client X a vraiment besoin de cette feuille de données Excel importée dans notre base de données d’applications cet après-midi", où vous n’aurez pas le loisir d’adapter le code de votre application au moment où un script SQL corrompu le fera. à l'heure.
C’est là que l’intégrité au niveau de la base de données sauvera votre bacon.
En outre, décrivez le développeur qui assume votre rôle dans cette société après votre départ et qui est ensuite chargé de modifier la base de données.
Vous haïra-t-il s'il n'y a pas de contrainte FK dans la base de données pour qu'il puisse dire quelles relations a une table avant de la modifier? ( Indice, la réponse est oui )
la source
Vous devriez avoir des relations dans la base de données.
Comme l’indique l’autre réponse, les performances de la vérification des contraintes seront bien meilleures dans cette base de données que dans votre application. La vérification des contraintes de base de données est l’un des atouts des bases de données.
Si vous avez besoin d'une flexibilité supplémentaire - par exemple, vos références croisées de bases de données notées -, vous pouvez supprimer les contraintes de manière délibérée et avec considération. La cohérence dans votre base de données signifie que vous avez la possibilité de modifier ces contraintes et la certitude de l’intégrité référentielle.
la source
Pouvez-vous vraiment vous permettre d'écrire et de tester du code renforçant l'intégrité référentielle lorsque vous avez du code de résolution de problèmes de domaine à écrire?
la source
Si vous ne validez pas l'intégrité, les contraintes, les relations, etc. des données au niveau de la base de données, il est beaucoup plus facile pour quiconque disposant d'un accès à la base de données de production (via tout autre client, y compris un outil d'accès à la base de données) de corrompre vos données.
Il est recommandé d'appliquer une intégrité des données aussi stricte que possible au niveau de la base de données. Croyez-moi, cela vous épargnera d'énormes maux de tête au fil du temps dans tout système non trivial. Si vous y réfléchissez bien, vous constaterez également plus rapidement les erreurs de logique d’application ou les erreurs d’exigences commerciales et les incohérences.
En outre, concevez votre base de données de la manière la plus normalisée et la plus atomique possible. Pas de tables "Dieu". Consacrez beaucoup d'efforts à la conception de votre base de données pour qu'elle soit aussi simple que possible, idéalement avec de nombreuses petites tables très bien définies individuellement, avec une responsabilité unique et soigneusement validées sur toutes les colonnes. La base de données est le dernier gardien de l'intégrité de vos données. Il représente le donjon du château.
la source
La plupart des gens disent essentiellement "oui, en général , vous définissez toujours les relations dans la base de données". Mais si les disciplines en informatique étaient si faciles, on nous appellerait "Lecteurs de logiciels" au lieu de "Ingénieurs". Je conviens en fait que les contraintes devraient figurer dans la base de données, à moins qu’il n’y ait une bonne raison de ne pas le faire , alors permettez-moi de donner quelques raisons qui pourraient être considérées comme bonnes dans certaines situations:
Dupliquer le code
Parfois, une certaine quantité de fonctionnalités pouvant être gérées par la base de données existe naturellement dans le code de l'application. Si l'ajout de contraintes de type base de données à la base de données est redondant, il peut être préférable de ne pas dupliquer la fonctionnalité, car vous enfreignez les principes de DRY et vous risquez d'empêcher la synchronisation de la base de données et du code de l'application.
Effort
Si votre base de données fait déjà ce qu’elle doit faire sans utiliser de fonctionnalités avancées, vous voudrez peut-être évaluer où votre temps, votre argent et vos efforts doivent être placés. Si l'ajout de contraintes empêche une défaillance catastrophique et permet ainsi à votre entreprise d'économiser beaucoup d'argent, cela en vaut probablement la peine. Si vous ajoutez des contraintes qui devraient tenir, mais que vous avez déjà la garantie de ne jamais être violées, vous perdez du temps et polluez votre base de code. Garanti est le mot clé ici.
Efficacité
Ce n'est généralement pas une bonne raison, mais dans certains cas, vous pouvez avoir une certaine exigence de performance. Si le code d'application peut implémenter certaines fonctionnalités plus rapidement que la base de données et que vous avez besoin de performances supplémentaires, vous devrez peut-être implémenter la fonctionnalité dans le code d'application.
Contrôle
Un peu lié à l'efficacité. Parfois, vous avez besoin d'un contrôle extrêmement fin sur la manière dont une fonctionnalité est mise en œuvre, et parfois, le traitement de la base de données la cache derrière une boîte noire que vous devez ouvrir.
Points de fermeture
La dernière chose que je dirai, c'est que vous saurez si vous ne devriez pas placer les fonctionnalités dans la base de données. Si vous n'êtes pas sûr, vous ferez probablement mieux d'utiliser les fonctionnalités de la base de données, car elles fonctionnent généralement très bien.
la source
Comme toujours, les réponses sont nombreuses. Pour moi, j'ai trouvé une règle simple (cela ne fonctionne que pour une approche centrée sur le modèle). D'habitude, je me concentre uniquement sur les différentes couches d'applications.
Si le modèle comprend plusieurs entités et qu'il existe des dépendances entre elles, la couche de persistance doit refléter ces dépendances avec ses possibilités. Donc, si vous utilisez un SGBDR, vous devez également utiliser des clés étrangères. La raison est simple. De cette façon, les données sont toujours valables sur le plan de la structure.
Toute instance effectuant un travail sur cette couche de persistance peut compter sur elle. Je suppose que vous encapsulez cette couche via une interface (service). Donc, voici le point où le design se termine et le monde réel commence.
En examinant vos points, en particulier les références inter-bases de données . Dans ce cas, oui, il ne devrait pas y avoir de référence implémentée dans le SGBDR, mais dans le service. Mais avant de suivre cette voie, ne vaudrait-il pas mieux en tenir compte lors de la conception?
Cela signifie, si je le sais déjà, qu'il y a des pièces qui doivent être stockées dans une base de données différente, alors je peux les mettre déjà là et les définir en tant que modèle séparé. Droite?
Vous indiquez également que la mise en œuvre de cette méthode dans le code est plus flexible . D'accord, mais cela ne semble-t-il pas être un dessin incomplet? Demandez-vous, pourquoi avez-vous besoin de plus de flexibilité?
Le problème de performances, dû aux contrôles d'intégrité dans la base de données, n'est pas réel. Le SGBDR peut vérifier ces choses beaucoup plus rapidement que toute implémentation de votre part. Pourquoi? Eh bien, vous devez faire face à la perturbation des médias, pas le SGBDR. Et il peut optimiser ces contrôles en utilisant ses statistiques, etc.
Donc, vous voyez, tout revient à la conception. Bien sûr, vous pouvez le dire maintenant, mais que se passe-t-il si une exigence inconnue apparaît, un changeur de jeu? Oui, cela pourrait arriver, mais de tels changements devraient être conçus et planifiés, etc. ; o)
la source
Vous avez de très bonnes réponses mais quelques points supplémentaires
L'intégrité des données est ce qu'une base de données est conçue pour faire
Faire une simultanéité appropriée avec une suppression semblable à FK au niveau de l'application serait horrible
L'expertise en intégrité des données est avec un DBA
Au niveau du programme, vous insérez, mettez à jour, mettez à jour en bloc, insérez en bloc, effacez en bloc ...
Client léger, client lourd, client mobile ...
L'intégrité des données n'est pas l'expertise d'un programmeur - beaucoup de code en double et quelqu'un gâcher ça monte
Supposons que vous soyez piraté - vous avez des problèmes de toute façon, mais un pirate informatique peut faire beaucoup de dégâts via un petit trou s'il n'y a pas de protection d'intégrité dans la base de données
Vous devrez peut-être manipuler des données directement via SQL ou TSQL
Personne ne se souviendra de toutes les règles de données
la source
Votre question n'a pas de sens: si vous pouvez modifier la base de données, c'est du code, si vous ne pouvez pas modifier la base de données, vous devrez créer vos contraintes ailleurs.
Une base de données que vous pouvez modifier contient autant de code qu'une ligne de ruby, javascript, c # ou ada.
La question de savoir où placer une contrainte dans votre système devrait se résumer à la fiabilité, au coût et à la facilité de développement.
la source
Il y a des tonnes de bonnes réponses ici. J'ajouterai que si vous avez une application écrite dans la langue Y, vous pouvez créer du code similaire à une contrainte de base de données dans Y. Et si quelqu'un souhaite accéder à votre base de données à l'aide de la langue Z, vous devrez à nouveau écrire le même code. Dieu vous aide si les implémentations ne sont pas exactement les mêmes. Ou lorsqu'un utilisateur professionnel averti se connecte à votre base de données à l'aide de Microsoft Access.
Mon expérience me dit que lorsque les gens ne veulent pas utiliser les contraintes de base de données, c'est parce qu'ils essaient de faire quelque chose de mal. Par exemple, ils essaient de charger en bloc des données et veulent laisser les colonnes non NULL, pendant un moment. Ils ont l'intention de "réparer cela plus tard", car la situation qui a rendu critique la contrainte non nulle "ne peut pas se produire dans ce cas." Un autre exemple pourrait être quand ils essaient de combiner deux types de données différents dans la même table.
Les personnes plus expérimentées prendront du recul et trouveront une solution qui n'impliquera pas de tenter de contourner une contrainte. La solution pourrait tout simplement être que la contrainte ne convient plus car l'activité a changé, bien sûr.
la source