web-dev-qa-db-fra.com

Conception de base de données pour la première fois: suis-je trop ingénieur?

Contexte

Je suis un étudiant CS de première année et je travaille à temps partiel pour la petite entreprise de mon père. Je n'ai aucune expérience dans le développement d'applications dans le monde réel. J'ai écrit des scripts en Python, des cours en C, mais rien de tel.

Mon père a une petite entreprise de formation et actuellement toutes les classes sont planifiées, enregistrées et suivies via une application Web externe. Il existe une fonction d'exportation/"rapports" mais elle est très générique et nous avons besoin de rapports spécifiques. Nous n'avons pas accès à la base de données réelle pour exécuter les requêtes. On m'a demandé de mettre en place un système de reporting personnalisé.

Mon idée est de créer les exportations CSV génériques et de les importer (probablement avec Python) dans une base de données MySQL hébergée au bureau tous les soirs, d'où je peux exécuter les requêtes spécifiques qui sont nécessaires. Je n'ai pas d'expérience dans les bases de données mais je comprends les bases. J'ai lu un peu sur la création de bases de données et les formulaires normaux.

Nous pouvons commencer à avoir des clients internationaux bientôt, donc je veux que la base de données n'explose pas si/quand cela se produit. Nous avons également actuellement quelques grandes sociétés en tant que clients, avec différentes divisions (par exemple, société mère ACME, division soins de santé ACME, division soins corporels ACME)

Le schéma que j'ai trouvé est le suivant:

  1. Du point de vue du client:
    • Les clients sont la table principale
    • Les clients sont liés au service pour lequel ils travaillent
      • Les départements peuvent être dispersés à travers un pays: RH à Londres, Marketing à Swansea, etc.
      • Les départements sont liés à la division d'une entreprise
    • Les divisions sont liées à la société mère
  2. Du point de vue des classes:
    • Les sessions sont le tableau principal
      • Un enseignant est lié à chaque session
      • Un statusid est donné à chaque session. Par exemple. 0 - Terminé, 1 - Annulé
      • Les sessions sont regroupées en "packs" de taille arbitraire
    • Chaque pack est attribué à un client

J'ai "conçu" (plus comme griffonné) le schéma sur un morceau de papier, essayant de le maintenir normalisé à la 3ème forme. Je l'ai ensuite branché sur MySQL Workbench et cela m'a rendu tout joli:
( Cliquez ici pour un graphique en taille réelle )

alt text
(source: maian.org )

Exemples de requêtes que je vais exécuter

  • Quels clients avec crédit restant sont inactifs (ceux sans cours prévu à l'avenir)
  • Quel est le taux de présence par client/département/division (mesuré par l'ID de statut dans chaque session)
  • Combien de cours un enseignant a-t-il eu en un mois
  • Signaler les clients qui ont un faible taux de fréquentation
  • Rapports personnalisés pour les départements RH avec des taux de présence des personnes dans leur division

Des questions)

  • Est-ce une ingénierie excessive ou est-ce que je me dirige dans la bonne direction?
  • La nécessité de joindre plusieurs tables pour la plupart des requêtes entraînera-t-elle une forte augmentation des performances?
  • J'ai ajouté une colonne "dernière session" aux clients, car ce sera probablement une requête courante. Est-ce une bonne idée ou dois-je garder la base de données strictement normalisée?

Merci pour votre temps

244
bob esponja

Quelques réponses supplémentaires à vos questions:

1) Vous êtes à peu près sur la cible pour quelqu'un qui aborde un problème comme celui-ci pour la première fois. Je pense que les indications des autres sur cette question jusqu'à présent la couvrent à peu près. Bon travail!

2 & 3) La performance que vous obtiendrez dépendra en grande partie d'avoir et d'optimiser les bons index pour vos requêtes/procédures particulières et, plus important encore, le volume d'enregistrements. À moins que vous ne parliez de plus d'un million d'enregistrements dans vos tableaux principaux, vous semblez être sur la bonne voie pour avoir une conception suffisamment intégrée pour que les performances ne soient pas un problème sur un matériel raisonnable.

Cela dit, et cela se rapporte à votre question 3, avec le début que vous avez, vous ne devriez probablement pas trop vous inquiéter de la performance ou de l'hyper-sensibilité à l'orthodoxie de normalisation ici. Il s'agit d'un serveur de rapports que vous créez, pas d'un backend d'application basé sur les transactions, qui aurait un profil très différent en ce qui concerne l'importance des performances ou de la normalisation. Une base de données sauvegardant une application d'inscription et de planification en direct doit tenir compte des requêtes qui prennent quelques secondes pour renvoyer des données. Non seulement une fonction de serveur de rapports a plus de tolérance pour les requêtes complexes et longues, mais les stratégies pour améliorer les performances sont très différentes.

Par exemple, dans un environnement d'application basé sur les transactions, vos options d'amélioration des performances peuvent inclure la refonte de vos procédures stockées et structures de table au nième degré, ou le développement d'une stratégie de mise en cache pour de petites quantités de données fréquemment demandées. Dans un environnement de génération de rapports, vous pouvez certainement le faire, mais vous pouvez avoir un impact encore plus important sur les performances en introduisant un mécanisme de capture instantanée dans lequel un processus planifié s'exécute et stocke des rapports préconfigurés et vos utilisateurs accèdent aux données de capture instantanée sans stress sur votre niveau de base de données sur une par demande.

Tout cela est un discours de longue haleine pour illustrer que les principes de conception et les astuces que vous utilisez peuvent différer compte tenu du rôle de la base de données que vous créez. J'espère que c'est utile.

42
Tom Crowe

Vous avez la bonne idée. Vous pouvez cependant le nettoyer et supprimer certaines des tables de mappage (a *).

Ce que vous pouvez faire, c'est dans le tableau Départements, ajoutez CityId et DivisionId.

A part ça, je pense que tout va bien ...

14
Reverend Gonzo

Il semble que vous conceviez avec un bon niveau de détail.

Je pense que les pays et les entreprises sont vraiment la même entité dans votre conception, tout comme les villes et les divisions. Je me débarrasserais des tables Pays et Villes (et Cities_Has_Departments) et, si nécessaire, ajouterais un drapeau booléen IsPublicSector à la table Companies (ou une colonne CompanyType s'il y a plus de choix que simplement Secteur Privé/Secteur Public).

De plus, je pense qu'il y a une erreur dans votre utilisation de la table des départements. Il semble que le tableau des départements serve de référence aux différents types de départements que chaque division client peut avoir. Si tel est le cas, il doit s'appeler DepartmentTypes. Mais vos clients (qui sont, je suppose, des participants) n'appartiennent pas à un TYPE de département, ils appartiennent à une instance de département réelle dans une entreprise. Dans l'état actuel des choses, vous saurez qu'un client donné appartient à un service RH quelque part, mais pas lequel!

En d'autres termes, les clients doivent être liés à la table que vous appelez Divisions_Has_Departments (mais que j'appellerais simplement Departments). Si tel est le cas, vous devez réduire les villes en divisions comme indiqué ci-dessus si vous souhaitez utiliser l'intégrité référentielle standard dans la base de données.

6
Larry Lustig

Les seuls changements que j'apporterais sont:
1- Changez votre VARCHAR en NVARCHAR, si vous allez à l'international, vous voudrez peut-être unicode.

2- Changez vos identifiants internationaux en GUID (uniqueidentifier) ​​si possible (cela pourrait être ma préférence personnelle). En supposant que vous arriviez finalement au point où vous avez plusieurs environnements (dev/test/staging/prod), vous souhaiterez peut-être migrer les données de l'un à l'autre. Avoir GUID Ids rend cela beaucoup plus facile.

3- Trois couches pour votre entreprise -> Division -> La structure du département peut ne pas suffire. Maintenant, cela peut être une ingénierie excessive, mais vous pouvez généraliser cette hiérarchie de manière à pouvoir prendre en charge n niveaux de profondeur. Cela rendra certaines de vos requêtes plus complexes, ce qui ne vaut peut-être pas le compromis. De plus, il se peut que tout client qui a plus de couches soit facilement "utilisable" dans ce modèle.

4- Vous avez également un statut dans la table des clients qui est un VARCHAR et n'a aucun lien avec la table des statuts. Je m'attendrais à un peu plus de clarté sur ce que représente le statut du client.

6
Jacob G

Soit dit en passant, il convient de noter que si vous générez déjà des fichiers CSV et que vous souhaitez les charger dans une base de données mySQL, LOAD DATA LOCAL INFILE est votre meilleur ami: http://dev.mysql.com/doc/ refman/5.1/en/load-data.html . Mysqlimport vaut également la peine d'être étudié, et est un outil de ligne de commande qui est essentiellement un bon emballage autour du fichier de chargement de données.

5
jrheard

Commentaires suivants basés sur le rôle de spécialiste de la Business Intelligence/Reporting et responsable de la stratégie/planification:

  1. Je suis d'accord avec la direction de Larry ci-dessus. À mon humble avis, ce n'est pas tellement trop conçu, certaines choses semblent un peu hors de propos. Pour rester simple, je marquerais le client directement sur un ID d'entreprise, une description de département, une description de division, un ID de type de département, un ID de type de division. Utilisez l'ID de type de département et l'ID de type de division comme références aux tables de recherche et aux champs de rapport/analyse internes pour une cohérence à long terme.

  2. La table des packs contient la colonne "Crédit", cela ne devrait-il pas être lié à la table de base du client, donc si de nombreux packs vous pouvez voir combien de crédit est dû pour les futures classes? L'application peut prendre en charge le calcul et le stocker de manière centrale dans la table Client.

  3. Les informations sur la société peuvent utiliser de nombreux autres champs, notamment l'adresse/le téléphone/etc. information. Je serais également prêt à ajouter des colonnes "DUN" D&B (Site/Branch/Ultimate) à long terme, Dun and Bradstreet (D&B) a un énorme catalogue de sociétés et vous trouverez plus tard sur la route leurs informations sont très utiles pour les rapports/analyses. Cela prendra en charge le problème de division multiple que vous mentionnez et vous permettra de regrouper leur hiérarchie pour les sous/divisions/branches/etc. de grands corps.

  4. Vous ne mentionnez pas le nombre d'enregistrements avec lesquels vous allez travailler, ce qui pourrait impliquer la mise en place d'une vaste initiative de développement qui aurait pu être effectuée plus rapidement et beaucoup moins de maux de tête avec un logiciel de "reporting" préemballé. Si vous ne traitez pas avec une grande base de données (<65 000) lignes, assurez-vous que MS-Access, OpenOffice (Base) ou les solutions de développement de rapport/application associées ne peuvent pas faire l'affaire. J'utilise moi-même un peu le logiciel APEX gratuit d'Oracle, il est livré avec leur base de données gratuite Oracle XE, il suffit de le télécharger sur leur site.

  5. FYI - Reporting insight: pour les grandes bases de données, vous avez généralement deux instances de base de données a) une base de données de transactions pour enregistrer chaque enregistrement détaillé. b) base de données de rapports (magasin de données/entrepôt de données) hébergée sur une machine distincte. Pour plus d'informations, recherchez google à la fois sur Star Schema et Snowflake Schema.

Cordialement.

3
Will

La plupart des choses ont déjà été dites, mais je pense que je peux ajouter une chose: il est assez courant pour les jeunes développeurs de s'inquiéter un peu trop des performances à l'avance, et votre question sur la jointure des tables semble aller dans cette direction. Il s'agit d'un anti-modèle de développement logiciel appelé ' Optimisation prématurée '. Essayez de bannir ce réflexe de votre esprit :)

Une dernière chose: croyez-vous que vous avez vraiment besoin des tableaux "villes" et "pays"? Une colonne "ville" et "pays" dans le tableau des départements ne suffirait-elle pas pour vos cas d'utilisation? Par exemple. votre application doit-elle répertorier les départements par ville et les villes par pays?

3
Hans Westerbeek

Je veux répondre uniquement à la préoccupation selon laquelle la jonction à plusieurs tables entraînera un impact sur les performances. N'ayez pas peur de normaliser car vous devrez faire des jointures. Les jointures sont normales et attendues dans les bases de données relationnelles et elles sont conçues pour bien les gérer. Vous devrez définir des relations PK/FK (pour l'intégrité des données, cela est important à prendre en compte lors de la conception), mais dans de nombreuses bases de données, les FK ne sont pas automatiquement indexés. Puisqu'ils seront utilisés dans les jointures, vous voudrez certainement commencer par indexer le FKS. Les PK reçoivent généralement un index sur la création car ils doivent être uniques. Il est vrai que la conception de l'entrepôt de données réduit le nombre de jointures, mais généralement, on ne parvient pas à l'entreposage de données tant que l'on n'a pas besoin d'accéder à des millions d'enregistrements dans un seul rapport. Même alors, presque tous les entrepôts de données commencent par une base de données transactionnelle pour collecter les données en temps réel, puis les données sont déplacées vers l'entrepôt selon un calendrier (nocturne ou mensuel ou selon les besoins de l'entreprise). C'est donc un bon début même si vous devez concevoir un entrepôt de données ultérieurement pour améliorer les performances des rapports.

Je dois dire que votre design est impressionnant pour un étudiant CS de première année.

2
HLGEM

Ce n'est pas trop conçu, c'est ainsi que j'aborderais le problème. Rejoindre, c'est bien, il n'y aura pas beaucoup de performances (c'est complètement nécessaire à moins que vous ne dénormalisiez la base de données, ce qui n'est pas recommandé!). Pour les statuts, voyez si vous pouvez utiliser un type de données enum à la place pour optimiser cette table.

1
Chris Dennett

J'ai travaillé dans le domaine de la formation/école et j'ai pensé que je ferais remarquer qu'il y a généralement une relation M: 1 entre ce que vous appelez des "sessions" (instances d'un cours donné) et le cours lui-même. En d'autres termes, votre catalogue propose le cours ("Espagnol 101" ou autre), mais vous pouvez en avoir deux instances différentes au cours d'un même semestre (Tu-Th enseigné par Smith, Wed-Fri enseigné par Jones).

En dehors de cela, cela semble être un bon début. Je parie que vous constaterez que le domaine client (graphiques menant à des "clients") est plus complexe que vous ne l'avez modélisé, mais n'allez pas trop loin avec cela jusqu'à ce que vous ayez des données réelles pour vous guider.

1
Larry OBrien

Quelques choses me sont venues à l'esprit:

  1. Les tables semblaient orientées vers le reporting, mais ne géraient pas vraiment l'entreprise. Je pense que lorsqu'un client s'inscrit, il y a essentiellement une commande passée pour le client assistant à une liste de sessions, et cette commande peut concerner plusieurs employés dans une même entreprise. Il semblerait qu'un tableau de "commandes" soit vraiment au centre de votre système et conduise votre capture de données et vos éventuels rapports. (Comparez les documents papier que vous avez utilisés pour gérer l'entreprise avec la conception de votre base de données pour voir s'il existe une correspondance logique.)

  2. Les entreprises n'ont souvent pas de divisions. Les employés changent parfois de division/département, peut-être même en milieu de session. Les entreprises ajoutent/suppriment/renomment parfois des divisions/départements. Assurez-vous que le possible changement de contenu en temps réel de vos tableaux ne rend pas les rapports/regroupements ultérieurs difficiles. Avec autant de données de contact réparties sur autant de tableaux, vous devrez peut-être appliquer une validation de saisie des données très stricte pour garder vos rapports significatifs et inclusifs. Par exemple, lorsqu'un nouveau client est ajouté, s'assurer que son entreprise/division/département/ville correspond aux mêmes valeurs que ses collègues.

  3. Le concept de "packs" n'est pas clair du tout.

  4. Étant donné que vous indiquez qu'il s'agit d'une petite entreprise, il serait surprenant que les performances soient un problème, compte tenu de la vitesse et de la capacité des machines actuelles.

0
joe snyder