Pourquoi ne devrais-je pas avoir une table pour plusieurs relations?

12

En supposant que j'ai plusieurs relations dans ma base de données, par exemple Store, Employee et Sale, et que je souhaite connecter des paires avec une relation binaire simple. Personnellement, je créerais des tables nommées Employee_Store et Employee_Sale avec une clé naturelle composée des clés étrangères.

Maintenant, mon collègue insiste sur la création d'une table pour plusieurs relations. Pour l'exemple ci-dessus, il pourrait y avoir une table appelée EmployeeLinks:

EmployeeLinks(
    IdLink int PK, 
    IdEmployee int FK null,
    IdStore int FK null,
    IdSale int FK null,
    LinkType int not null
)

Veuillez m'aider avec de bonnes raisons pour lesquelles ce n'est pas une bonne idée. J'ai mes propres arguments, mais je voudrais les garder confidentiels et entendre vos opinions impartiales.

ÉDITER:

Initialement, le tableau ci-dessus n'aurait pas de clé primaire (!). Parce que les clés étrangères autorisent null, une clé de substitution est la seule option.

Tomasz Pluskiewicz
la source
3
C'est comme OTLT ou EAV mais pire parce qu'il prolifère des colonnes plutôt que des lignes!
onedaywhen le

Réponses:

13

Que propose votre collègue comme clé primaire pour cette table de liens?
Les colonnes de clé primaire ne peuvent pas être NULL bien sûr: le tableau ci-dessus a nullable.

Il n'y a pas d'identifiant de ligne naturel (ce qu'est un PK) dans l'exemple ci-dessus (une colonne IDENTITY n'est pas une clé primaire), donc il échoue dans tout processus de modélisation. Ne pensez même pas à créer des tables sans modèle (ERD, ORM, IDEF1X, peu importe)

Vous auriez également besoin de contraintes CHECK pour vous assurer que vous n'avez pas de liens à 3 voies.

Enfin, vous vous égarez dans les territoires de forme normale 4e et 5e, mais pour de mauvaises raisons.

Je ne trouve aucun exemple sur Internet: cela montre à quel point c'est stupide

gbn
la source
4
+1 pourI can't find any examples on the internet: that shows how stupid this is
JNK
J'ai précisé la clé primaire. En outre, apparemment, mon collègue a déjà rencontré un tel design avant ou alors on me dit
Tomasz Pluskiewicz
@Tomasz Pluskiewicz: Une clé de substitution n'est pas la clé primaire! Il est choisi pour compléter la clé naturelle au moment de la mise en œuvre. Voir dba.stackexchange.com/a/13779/630. En outre, votre collègue doit nous montrer un article faisant autorité qui illustre cette technique. J'ai vu des tas de détritus dans mon temps, mais je ne les répète pas ...
gbn
12

La première raison pratique à laquelle je peux penser est la performance.

Dans un modèle "traditionnel", vous pouvez avoir un index unique sur Idemployee, Idstoreou quels que soient les champs, et obtenir d'excellentes performances sur les recherches. Il est également facile à entretenir pour les inserts. Les index uniques vous permettent de fusionner des jointures plus fréquemment, ce qui peut rendre beaucoup de JOINs incroyablement rapides.

Dans votre modèle d'exemple, pour obtenir des performances décentes, vous aurez besoin d'avoir un index de champ unique sur chaque champ FK de la table au minimum, idéalement un index de couverture sur toutes les combinaisons qui seront référencées, à savoir:

  • Employé / Magasin
  • Employé / Vente

Je ne sais pas exactement quel type de lien est, mais si vous le référencez, il devrait probablement être indexé.

Ces index devront être conservés pour chaque ligne de la table, que le champ soit rempli ou non. Vous pouvez ajouter un filtre mais cela deviendra difficile aussi avec autant de combinaisons.

Cela compliquera également votre logique. Vous devrez soit effectuer une recherche sur l'employé, trouver une ligne avec une valeur de magasin vide et mettre à jour; ou, insérez simplement une nouvelle ligne pour chaque nouveau lien, ce qui va à l'encontre de l'objectif de consolidation des champs.

Fondamentalement, vous utiliserez PLUS d'espace disque, vous aurez PLUS d'index à maintenir et compliquerez votre logique pour pratiquement aucune raison. Le seul "avantage" est qu'il y a moins de tables à gérer.

JNK
la source
La colonne LinkType est quelque chose d'un discriminateur. Dire simplement quelle paire une ligne se rapporte réellement. Ajoute juste à l'engin si vous me demandez.
Tomasz Pluskiewicz
@TomaszPluskiewicz Je pense que la meilleure façon de lui montrer pourquoi ça craint est de construire un exemple de jeu de données avec les deux types de tables et d'exécuter quelques requêtes. Son modèle sera beaucoup plus lent qu'un modèle traditionnel
JNK
4

Placer plusieurs relations dans une même table peut être utile si ces relations ont les mêmes attributs et / ou si vous souhaitez agréger des données sur plusieurs relations.

Cela est nécessaire si les types de relations sont définis par l'utilisateur au moment de l'exécution. Cependant, c'est rarement vraiment le cas.

Dans votre exemple, les relations ne partagent pas d'attributs, les relations référençant même deux tables différentes. Cela rend difficile l'application des contraintes et la conception est également moins intuitive.

Je ne choisirais cette conception que si la création de tables coûte littéralement de l'argent.

JMD Coalesce
la source