Est-ce une façon ridicule de structurer un schéma de base de données ou est-ce que quelque chose me manque complètement?

61

J'ai beaucoup travaillé avec les bases de données relationnelles et je pense comprendre assez bien les concepts de base d'une bonne conception de schéma. J'ai récemment été chargé de reprendre un projet où la base de données avait été conçue par un consultant hautement rémunéré. S'il vous plaît laissez-moi savoir si mon intestin instinct - "WTF ??!?" - est justifié, ou est-ce un gars si génial qu'il opère hors de mon royaume?

DB en question est une application interne utilisée pour saisir les demandes des employés. En regardant une petite partie de celle-ci, vous avez des informations sur les utilisateurs et des informations sur la demande en cours. Je concevrais ceci comme si:

Table utilisateur:

UserID (primary Key, indexed, no dupes)
FirstName
LastName
Department

Table de demande

RequestID (primary Key, indexed, no dupes)
<...> various data fields containing request details
UserID -- foreign key associated with User table

Simple, non?

Le consultant l'a conçu comme suit (avec des exemples de données):

Tableau d'utilisateurs

UserID  FirstName   LastName
234     John        Doe
516     Jane        Doe
123     Foo         Bar

DépartementsTable

DepartmentID   Name
1              Sales
2              HR
3              IT

UserDepartmentTable

UserDepartmentID   UserID   Department
1                  234      2
2                  516      2
3                  123      1

RequestTable

RequestID   UserID   <...>
1           516      blah
2           516      blah
3           234      blah

La base de données entière est construite comme ceci, avec chaque donnée encapsulée dans sa propre table, avec des ID numériques reliant tout. Apparemment, le consultant avait entendu parler d’OLAP et souhaitait connaître la «vitesse de recherche des nombres entiers».

Il dispose également d'un grand nombre de procédures stockées pour faire référence à toutes ces tables.

Cette conception est-elle valide pour une base de données SQL de taille petite à moyenne?

Merci pour les commentaires / réponses ...

Jim
la source
12
Oh, si cela vous fait dire WTF, alors vous n'avez probablement pas vu de tables avec plus de 200 colonnes et procédures stockées de plus de 1000 lignes.
Job le
42
+1 pour ne pas supprimer après un sentiment d'embarras. Merci de laisser ceci pour que les autres puissent apprendre.
Wayne Koorts
2
@Job - en fait, je ne l'ai pas - je ne suis pas un administrateur de base de données (assez évident maintenant! Lol), mon seuil SQL WTF est donc assez bas. Bien que, manquant complètement le but de la conception du consultant, je suis capable de gérer mes propres capacités. Avez-vous déjà eu une journée où vous vous sentiez stupide ?
Jim
9
@ Jim: Félicitations, vous avez transformé une journée muette en une journée éclairée .
Wayne Koorts
3
Maudissez ces consultants hautement payés!
davidsleeps

Réponses:

73

Cela me semble parfaitement sensé. C'est juste très normalisé, ce qui confère beaucoup de flexibilité que vous n'auriez pas autrement. Les données dénormalisées sont une douleur dans le dos.

Blrfl
la source
Votre réponse est parfaitement logique. Si vous examinez ma question et le schéma, c'est peut-être juste le nombre de tables qu'il utilise qui m'a confondu. J'ai grandement simplifié l'exemple de ma question, mais je vois à quel point le concept est valable: il scinde les choses beaucoup plus que je ne le ferais. Soupir, je suppose que c'est une bonne chose que je ne sois pas administrateur de base de données! :)
Jim
Apprenez à concevoir selon la règle des dix minutes: "Ce qui est vrai maintenant ne le sera probablement pas dans dix minutes." Assurez-vous que vos conceptions peuvent faire face au changement.
Blrfl
1
Ce schéma présente en fait l’avantage que lorsqu’un employé est inséré, son service doit exister.
Simon Richter
@SimonRichter: Ce n'est pas vrai. L'employé peut être créé sans aucun département existant, et aussi l'inverse.
Daniel Dinnyes
@SimonRichter L'avantage de cette conception est, d'une part, que le ministère est une entité distincte et, d'autre part, qu'il existe une relation plusieurs à plusieurs entre ministère et employé, contrairement à l'exemple des PO, où il s'agissait de to-one-ish "(ne peut pas dire plusieurs-à-un, car aucune entité de département distincte ne faisait référence à une relation).
Daniel Dinnyes
48

Je ne pense pas que ce soit une WTF soit garantie ou que le type fait tout type de conception de génie fou - c'est une normalisation de base de données assez standard.

La raison pour la table de département est que si vous ne mettez pas les départements dans une table séparée, vous devrez traiter les utilisateurs dans les départements "Ventes", "Ventes", "Vendeurs", "Voiles" et "Ventes", sauf si vous faites quelque chose pour l'empêcher. Et avoir la table supplémentaire est (une partie de) la meilleure façon que je connaisse pour le faire.

Qu'il y ait ou non une table UserDepartment est un appel plus difficile, ce qui signifie bien sûr qu'aucune des décisions prises n'est folle. D’un côté, c’est pénible lorsque toute la conception et la logique de votre table ont supposé un département par utilisateur, puis que cela change. D’autre part, faire une jointure supplémentaire sans raison pendant des années et des années est une possibilité réelle et également pénible.

Personnellement, je conviens avec vous que la table UserDepartment est probablement excessive. Même s'il est inclus, il est probable qu'avec le temps, les gens écriront des requêtes supposant qu'il n'y a qu'un seul utilisateur par département. Vous vous retrouverez ainsi avec le pire des deux mondes: une jointure supplémentaire sans raison avant d'avoir besoin de la table, et le code ne fonctionnant pas de toute façon une fois plus d'un service par utilisateur est autorisé.

EDITER - Si les règles de gestion sont claires, la détermination de la relation plusieurs à plusieurs est un facteur déterminant. Si vous ne savez pas comment un utilisateur de plusieurs départements fonctionnerait, il serait inutile d'ajouter la table, car votre code ne peut pas correctement traiter les cas où un utilisateur appartient à plusieurs départements.

Imaginez que vous ayez autorisé plusieurs départements par utilisateur, au cas où. Vous avez ensuite implémenté une règle de gestion pour l'attribution de commissions, basée sur le service. Ensuite, plusieurs départements ont été autorisés. Heureusement, vous avez également eu la clairvoyance d’écrire votre code de commission de manière à en tenir compte. Malheureusement, vous avez ajouté les commissions de chaque département pour les utilisateurs des deux. La direction souhaitait que vous vous basiez sur le rôle des personnes pour chaque vente. Alors, à quoi bon avoir la table à l'avance? Qu'en est-il des autres tables que vous aviez "juste au cas où" qui ne sont jamais nécessaires?

PLUS TARD - Une autre raison pour laquelle le consultant aurait peut-être voulu ajouter tous ces tableaux intermédiaires est abordée dans cette question complémentaire , dont les réponses donnent certaines raisons pour lesquelles la refactorisation d'une base de données est généralement plus difficile que le code de refactorisation, ce qui aurait tendance à vous pousser vers l'approche "mettre dans toutes les tables que vous pourriez avoir besoin".

psr
la source
Je pense que vous avez mis en mots ce que ma WTF était - le gars utilise des tonnes de ces tables intermédiaires, et ça me semblait tellement stupide. Maintenant que j'ai divisé le texte en un exemple beaucoup plus petit pour cette question, je me sens plutôt stupide de l'avoir publiée car cela ne semble pas si grave.
Jim
5
Comme vous pouvez le constater dans de nombreux commentaires, il existe un scepticisme sain à propos des commentaires "il n'y aura jamais qu'un seul X par Y". Le consultant se couvre de "comment se fait-il qu'il ne puisse y avoir qu'un seul X par Y" plaintes. Certains d'entre eux vont probablement venir. Mais il ne sera pas responsable du maintien du code comportant de nombreuses jointures (pas trop mal, mais plus difficile) et qui doit être correct par rapport à des règles commerciales qui n'existent pas encore (mauvais) - imaginez la question "pourquoi les utilisateurs obtiennent-ils TOUT les autorisations de chaque département, ils devraient obtenir le plus bas de chaque autorisation "ou une telle.
psr
@ psr Je pense qu'il y a une faute de frappe: les requêtes "qui supposent qu'il n'y a qu'un utilisateur par département" ne devraient-elles pas être des requêtes qui supposent qu'un utilisateur appartient à un seul département "?
BiAiB
@BiAiB - vous avez raison, c'est ce que je voulais dire.
psr
14

Si l'exigence est d'avoir plusieurs départements par utilisateur, cette conception est logique. Le seul inconvénient est d' UserDepartmentTableavoir une clé de substitution UserDepartmentIDinutile (créez simplement la UserIdet DepartmentIdune clé primaire composite).

Si un utilisateur n'appartient qu'à un seul département, votre conception a du sens (bien qu'une table de consultation de département reste une bonne chose).

Oded
la source
18
... Jusqu'à ce que plusieurs départements soient possibles par utilisateur.
Blrfl
1
Justement, @Blrfl. Ce qui ne se passera pas aujourd'hui, c'est le PDG de demain qui subit un anévrisme parce qu'il ne le fait pas.
Adam Crossland le
2
Pour comprendre ce qui est digne de ce type de traitement, il faut comprendre le problème. Dans certaines applications, il peut être important de savoir que le numéro d’employé 3804 est connu de la société sous le nom de Ann Smith et Ann Jones (après le mariage), ce qui rendrait tout à fait normal de normaliser le nom de la liste des employés. Dans le cas de Jim, il pourrait être intéressant d’agrandir la table de répartition pour conserver un historique afin que, si Ann passe des RH à l’informatique, le fait qu’une ancienne demande qui lui est liée puisse refléter le fait qu’il s’agit bien de la demande des RH et non des TI.
Blrfl
8
YAGNI - les bases de données peuvent être refactorisées.
JeffO
2
@Oded, certains mappeurs ORM tels qu'Entity Framework ne fonctionnent pas bien avec les tables ayant une clé primaire composite.
maple_shaft
5

Certaines exigences ne sont pas claires dans votre question. La réponse correcte dépend de ce que veut votre client - Si j'étais vous, je demanderais au client ce qu'il en est:

0-Quelle est la différence entre un utilisateur et un employé?

1-En supposant qu'un employé = utilisateur, que se passe-t-il si un employé change de département?

2-Un groupe d’employés peut-il faire une demande?

3-Un employé peut-il appartenir à plusieurs départements? Qu'en est-il du PDG

4-Y a-t-il un sous-ensemble d'employés autorisés à faire des demandes?

5-Qu'advient-il de la demande lorsqu'un enregistrement d'employé est supprimé (si jamais)?

6-Pouvez-vous supprimer une demande? Que se passe-t-il lorsque la demande est supprimée (veillez à ne pas supprimer l'enregistrement d'employé par RI)

7-L'employé peut-il faire la "même" demande plus d'une fois (définir la "même")

8-Comment traiter les demandes des employés lorsqu'ils quittent l'entreprise (annuler leurs demandes ou supprimer les demandes?)

Il peut y avoir plus de questions, mais mon point est que la solution dépend d' exigences précises et de la portée du projet. Une fois que cela est déterminé, le schéma peut être dérivé directement. En conséquence, les deux solutions présentées peuvent être correctes.

Aucune chance
la source
Ce sont d'excellentes questions à clarifier avant de concevoir ce type de schéma. J'aime votre flux de logique.
@ Surfer513: j'apprécie votre gentil commentaire.
NoChance
1

J'aimerais ajouter quelques notes explicites expliquant certains des avantages potentiels de l'utilisation d'une table de jointure de la même manière que votre consultant hautement rémunéré.

  • Correctement indexé (par exemple, si UserDepartmentTable indexe les deux clés étrangères), seule une perte de performance faible d’une table de jointure de ce type est due au fait que les clés étrangères ne sont pas uniques. Si les clés étrangères sont garanties comme étant uniques, selon la théorie de la base de données, que je connais bien, la recherche UserDepartmentTable.Departmentn'est pas plus difficile que de rechercher une autre colonne du Usertableau.
  • La table de jointure vous donne plus de flexibilité pour configurer d'autres informations sur l'association entre l'utilisateur et le service (par exemple, les horodatages lors de la création).
  • La table de jointure vous permet de "version" assez facilement l'association (par exemple, lorsqu'un utilisateur change de département, déclenche un indicateur booléen d'index comme UserDepartmentTable.Activefalse et crée une nouvelle association active). Il est également possible d'avoir un versioning d'association de département avec le modèle à deux tables (utilisateur et département uniquement), mais il est plus difficile et nécessite l'ajout d'au moins une colonne ou des acrobaties de base de données afin d'éviter la duplication de clés primaires.
  • Il vous permet d’affecter assez facilement des associations un-à-plusieurs, plusieurs-un-plusieurs-plusieurs-plusieurs.

Cela étant dit, il y a plusieurs raisons de NE PAS faire ce que votre consultant hautement rémunéré a fait.

  • Tous les avantages ci-dessus anticipent tous les besoins futurs, compliquant de manière excessive les choses pour le présent. Ce n'est pas conforme à YAGNI. Par la suite, il sera très difficile d’écrire une migration qui passera de votre modèle à deux tables à un modèle à tables jointes. Vous pouvez le faire lorsque le besoin de l’entreprise s’en fait sentir. Le faire avant peut être déroutant.
  • Cela déroute les autres développeurs. Bien que, oui, je dirais que l'attente d'un développeur web de votre envergure (lorsque vous examinez les décisions des consultants) serait de comprendre et de reconnaître une table de jointure, c'est toujours plus compliqué que nécessaire et compte tenu du manque de besoins commerciaux, cela crée de la confusion.
Steven
la source
bonne analyse - cependant, je ne dirais pas que j’ai une certaine stature en tant que dev dans mon travail quotidien, sauf que je suis le seul ici à savoir quoi que ce soit à propos de db / c # / vb / etc ... alors suppose que je fais partie temps dev par défaut. C'est un projet assez petit, les consultants n'ont donc laissé que quelques tables et m'ont rejoint en disant "wtf" (mais grâce à vous, bon peuple, je dis maintenant "oic ...")
Jim
Sujet assez ancien, mais toujours d'actualité ... la refactorisation peut s'avérer très difficile. Imaginez que vous ayez besoin de plusieurs départements à l'avenir au lieu d'un, mais que vous n'ayez qu'un ID de département dans Users en tant que FK. Vous vous retrouverez probablement avec des références dupliquées (Users.DeptID et UsersDepartmentsTable) ou une mémoire complète, comme des listes séparées par des virgules dans Users.DeptID ou XML. La solution correcte ne pourrait pas être facilement ajoutée, comme suggéré par YAGNI ou KISS, mais serait obstruée.
Erik Hart
0

Sans une structure complète d'informations nécessaires, je ne peux pas dire si c'est terrible ou non. Mais au moins, la pièce présentée n’est pas de type "WTF". Cela semble juste être la 3-ème forme normale de structure de données (enfin, théoriquement, nous avons aussi les 4 et 5 également)

Certaines discussions peuvent avoir lieu pour UserDepartmentTable entre deux écoles de clés "naturelles" et "artificielles" dans la pièce illustrée. Rien de plus, comme je peux le voir

La normalisation est de bonne règle DB-développeur / concepteur pour beaucoup de raisons, * de * normalisations sont utilisés parfois au milieu de l ' évolution de la vitesse-gagnant la plupart du temps

Badger paresseux
la source