Il y a deux tableaux: Deal
et DealCategories
. Une transaction peut avoir plusieurs catégories de transactions.
Donc, la bonne façon devrait être de créer un tableau appelé DealCategories
avec la structure suivante:
DealCategoryId (PK)
DealId (FK)
DealCategoryId (FK)
Cependant, notre équipe d'externalisation a stocké les multiples catégories dans le Deal
tableau de cette façon:
DealId (PK)
DealCategory -- In here they store multiple deal ids separated by commas like this: 18,25,32.
J'ai l'impression que ce qu'ils ont fait est mal, mais je ne sais pas comment expliquer clairement pourquoi ce n'est pas juste.
Comment dois-je leur expliquer que c'est faux? Ou peut-être que c'est moi qui me trompe et c'est acceptable?
database-design
foreign-key
Sarawut Positwinyu
la source
la source
Réponses:
Oui, c'est une terrible idée.
Au lieu d'aller:
Vous devez maintenant aller:
Ensuite, vous devez faire des choses dans votre code d'application pour diviser cette liste de virgules en nombres individuels, puis interroger la base de données séparément:
Ce motif de conception découle soit d'une incompréhension complète de la modélisation relationnelle (vous n'avez pas à avoir peur des tableaux. Les tableaux sont vos amis. Utilisez-les), soit d'une croyance bizarrement erronée qu'il est plus rapide de prendre une liste séparée par des virgules et de la diviser dans le code d'application que pour ajouter une table de liens (ce n'est jamais le cas ). La troisième option est qu'ils ne sont pas suffisamment confiants / compétents avec SQL pour pouvoir configurer des clés étrangères, mais si c'est le cas, ils ne devraient rien avoir à voir avec la conception d'un modèle relationnel.
SQL Antipatterns (Karwin, 2010) consacre un chapitre entier à cet antipattern (qu'il appelle «Jaywalking»), pages 15-23. En outre, l'auteur a posté une question similaire sur SO . Les points clés qu'il note (appliqués à cet exemple) sont:
COUNT
,SUM
etc.), là encore, varient de «compliquées» à «presque impossibles». Demandez à vos développeurs comment ils vous obtiendraient une liste de toutes les catégories avec un décompte du nombre d'offres dans cette catégorie. Avec une conception appropriée, cela représente quatre lignes de SQL.VARCHAR
limitations de longueur de liste. Bien que si vous avez une liste séparée par des virgules de plus de 4000 caractères, il est probable que le monstre sera lent comme l'enfer de toute façon.TLDR: C'est une conception fondamentalement imparfaite, elle n'évolue pas bien, elle introduit une complexité supplémentaire, même pour les requêtes les plus simples, et dès le départ, elle ralentit votre application.
la source
C'est en fait une bonne conception si vous avez seulement besoin de rechercher les catégories pour une offre donnée.
Mais c'est terrible si vous voulez connaître toutes les offres dans une catégorie donnée.
Et cela rend également très difficile et susceptible d'erreurs de faire autre chose - comme les mises à jour, les comptages, les jointures, etc.
La dénormalisation a sa place, mais vous devez garder à l'esprit qu'elle optimise pour un type de requête au détriment de toutes les autres que vous pourriez faire contre les mêmes données. Si vous savez que vous interrogerez toujours dans un même modèle, cela pourrait vous donner un avantage d'utiliser la conception dénormalisée. Mais s'il y a une chance que vous ayez besoin de plus de flexibilité dans les types de requêtes, respectez une conception normalisée.
Comme toute autre forme d'optimisation, vous devez savoir quelles requêtes vous allez exécuter avant de pouvoir décider si la dénormalisation est justifiée.
la source
select * from DealCategories where DealId in (1,2,3,4,...)
. Vous avez plus d'expérience que moi en matière de conception de bases de données, alors peut-être avez-vous de bonnes raisons dans certains cas pour un tel "réglage extrême" dans des cas très spécifiques. Ma seule idée pour justifier cela est uneselect
charge très élevée sur Deal / DealCategory. Cela me ressemble beaucoup à une équipe externalisée sans aucune connaissance en conception de base de données, au-delà de la création de tables, elle l'a créée.Plusieurs valeurs dans une colonne sont contre la 1ère forme normale.
Ce n'est également absolument aucun gain de vitesse, car les tables doivent être liées dans la base de données. Vous devez d'abord lire et analyser une chaîne, puis sélectionner toutes les catégories pour le "Deal".
L'implémentation correcte serait une table de jonction comme "DealDealCategories", avec DealId et DealCategoryId.
Mauvaise implémentation de la hiérarchie?
En outre, un FK dans DealCategories vers un autre DealCategory ressemble à une mauvaise implémentation d'une hiérarchie / arborescence de DealCategories. Travailler avec des arbres via une relation Parent ID (appelée liste de contiguïté) est pénible!
Vérifiez les ensembles imbriqués (bons à lire, mais difficiles à modifier) et les tables de fermeture (meilleures performances globales, mais peut-être une utilisation élevée de la mémoire - probablement pas trop pour vos DealCategories) lors de la mise en œuvre des hiérarchies!
la source