web-dev-qa-db-fra.com

Conception de la base de données pour des objets avec plusieurs états

contexte

Je concevons une base de données qui, simplifiée, devraient pouvoir gérer les utilisateurs envoi de demandes d'emploi les uns aux autres et, après cela, un travail peut être démarré, terminé et examiné. La conception devrait être évolutive (penser des millions d'utilisateurs).

Approches que j'ai envisagées :

Table Gargantuan

Une approche, probablement pas la meilleure, serait de stocker tout simplement tous les emplois en une seule table jobs. Cette table aurait besoin d'une colonne state pour représenter quel état est actuellement sous (par exemple, ACCEPTED, STARTED, FINISHED, REVIEWED, _ etc). Le plus gros problème avec cette approche que je peux voir est que des emplois dans différents États ont différents types de données qui leur sont pertinentes. Par exemple, une demande d'emploi a un prix convenu préliminaire, mais cela pourrait changer avant le début du travail et changer à nouveau avant la fin du travail. Cela pourrait bien sûr être résolu en ajoutant simplement plus de colonnes à la table et de les nommer correctement, mais cela deviendra probablement une énorme performance d'un goulot d'étranglement très tôt pour avoir une table contenant tous les différents types de données possibles pour tous les états éventuels d'un travail.

Différentes tables pour différents états

Cette approche serait d'avoir plusieurs tables, par exemple job_requests, jobs_started, jobs_finished, les tables qui peuvent à leur tour se substituer, par ex. job_requests pourrait avoir les sous-états PENDING, ACCEPTED, tandis que le jobs_finished la table aurait les sous-états COMPLETED, CANCELLED, REVIEWED.

Avec cette approche, chaque table ne contient que des données pertinentes pour l'état actuel, mais d'autre part, certaines données peuvent être dupliquées (par exemple, les ID utilisateur du demandeur d'emploi et le récepteur d'emploi - d'autre part, cette information pourrait être stocké dans une autre table?). Le problème de cette approche est que je ne peux pas penser à une bonne solution sur la manière d'archiver toutes les informations lors de la transition entre les États. Par exemple, une fois qu'une demande d'emploi a été acceptée, puis a commencé, il convient de supprimer de la job_requests table et déplacé dans le jobs_started Tableau, mais c'est juste une question de temps avant qu'un intervenant ne veuille savoir, par exemple, combien de temps le délai moyen entre une demande de travail créé, jusqu'à ce qu'il soit démarré, auquel cela a été démarré, auquel j'avais besoin des données de la table Job_requests être capable de le calculer.

Il semble que ce type de problème soit facile à résoudre, mais je ne peux vraiment penser à une bonne solution qui "se sent bien", une solution que je monte avec la maidée et que je peux immédiatement penser à un certain nombre de choses qui font la solution mauvaise.

Très reconnaissant pour tous les commentaires ou conseils sur les approches que je pouvais prendre. Merci d'avance!

8
Atra Azami

On dirait que vous avez 3 catégories importantes de données que vous essayez de stocker:

  1. Données générales du travail (ID de travail, ID de demandeur d'emploi, ID du récepteur d'emploi, etc.)
  2. Transitions de l'état (travail commencé, travail terminé)
  3. Données d'emploi spécifiques à l'État
  4. (Facultatif) Événements liés au travail (prix modifié, utilisateur du récepteur d'emploi réaffecté, etc.)

La clé est de séparer les données comme des événements de tout le reste.

Conception de schéma

Voici quelques détails:

1. Table des emplois généraux

Toutes les informations qui ne sont pas spécifiques à l'État vont dans la table (disons) "emplois". Clé primaire générée automatiquement: job_id

2. Table de transition de l'état

Toutes les informations sur les transitions de l'état vont dans la table "job_state_transitions", qui pourraient avoir les colonnes suivantes:

  • job_transition_id
  • job_id
  • créé à
  • de_state
  • établir

Idéalement, cette table est uniquement ajoutée. Rien n'est mis à jour ou supprimé ici.

Utilisation d'une telle table, vous pouvez trouver le dernier statut de tout travail particulier en sélectionnant la dernière ligne d'un emploi donné à partir de la table Job_Transitions. Vous pouvez également dénormaliser cela et introduire une colonne "Job_state", dont le contenu est mis à jour chaque fois qu'une nouvelle ligne est insérée dans la table Job_Transition (les procédures stockées pourraient aider ici si c'est votre truc).

Vous pouvez également faire toutes sortes d'analyses sur les transitions de l'état, car les données de synchronisation sont préservées (Created_AT est un champ de date/heure pouvant aider avec cela)

3. Données professionnelles spécifiques à l'état

Toutes les données spécifiques à l'État sont dans les tables "[état] -jobs". Touche principale: une pièce d'identité de séquence. Index principal: job_transition_id

4. Données d'événement facultatives

Vous pouvez également introduire une table "Audit Trail" qui vous permet de suivre diverses modifications que les utilisateurs peuvent demander à chaque travail, comme votre "changement convenu". Il s'agit d'une généralisation du tableau de transition d'état: une table principale contenant des événements et d'une table supplémentaire pour chaque type d'événement (par exemple, prix de prix_changes avec job_id, créé_at, from_price et t-à-laprice colonnes).

Échelle à des millions d'utilisateurs

Si la table principale "Emplois" grandit pour être difficile à manier, vous pouvez le tordre par job_id ou demande_user_id ou quelque chose comme ça.

De même, la table des événements devrait être annexée uniquement et peut être tournée ou purgée d'événements liés à des emplois terminés.

10
pbkhrv

Que diriez-vous d'un hybride des deux? Une grande table avec un Employe et un état (et peut-être d'autres informations communes à tous les emplois et états), avec d'autres tables pour gérer les informations supplémentaires sur l'état. Cela réduit (ou élimine) la duplication des données, mais empêche les choses plus gérables.

4
Jim Nutt

Vous voudrez peut-être envisager d'utiliser une base de données NOSQL pour ces données spécifiques. De cette façon, vous pouvez simplement mettre votre object dans un enregistrement, quelle que soit les "colonnes".

Selon le système de base de données choisi (et la solution mise en œuvre), vous pourrez "écraser" un enregistrement avec différentes données si vous le souhaitez. Bien sûr, vous pouvez également enregistrer vos données historiques et juste PUT un nouvel enregistrement dans la base de données.

Vous pouvez commencer avec cet enregistrement:

myStartedObject{
    id: 1,
    state:  'started',
    agreedUponPrice:    100.00,
    someOtherData:  'x'
}

et avec le temps, il changerait quelque chose comme celui-ci ou si vous souhaitez conserver les enregistrements d'historique, le id changerait.:

myFinishedObject{
    id: 1
    state:  'finished',
    finishedPrice:  209.00,
    someFinishedData:   'y'
}

Stocker toute la date de l'état à l'intérieur de l'objet est également une option bien sûr, quelque chose comme ceci:

myObject
{
    id: 1,
    states: [{ state: 'started', agreedUponPrice: 100.00, someOtherData: 'x'}, 
        { state: 'finished', finishedPrice: 209.00, someFinishedData: 'y'}]
}

N'oubliez pas que ce n'est sûrement pas la balle d'argent, mais cela pourrait être quelque chose à considérer comme vous indiquez que votre "schéma" est assez lâche et vous ne voulez pas polluer vos SGBDM avec toutes ces colonnes.

Gardez également à l'esprit, tout SGBDM peut le faire aussi. Je sais dans MS SQL, vous avez le type de données XML. Avec cela, vous pouvez stocker vos données dans cette colonne XML. Cette colonne XML peut contenir votre objet désherialisé par exemple. Ce n'est pas une solution "réelle" NOSQL, mais cela ressemble un peu comme un.

1
Jan_V