Quelle architecture est recommandée pour fournir du stockage pour un schéma de base de données logique dynamique?
Pour clarifier: lorsqu'un système doit fournir le stockage d'un modèle dont le schéma peut être étendu ou modifié par ses utilisateurs une fois en production, quelles sont les bonnes technologies, modèles de base de données ou moteurs de stockage qui permettront cela?
Quelques possibilités pour illustrer:
Toutes les réponses basées sur l'expérience du monde réel seraient grandement appréciées
Ce que vous proposez n'est pas nouveau. Beaucoup de gens l'ont essayé ... la plupart ont constaté qu'ils recherchaient une flexibilité "infinie" et finissaient par beaucoup, beaucoup moins que cela. C'est le "roach motel" de la conception des bases de données - les données entrent, mais il est presque impossible de les sortir. Essayez de conceptualiser l'écriture du code pour TOUT type de contrainte et vous verrez ce que je veux dire.
Le résultat final est généralement un système BEAUCOUP plus difficile à déboguer, à entretenir et rempli de problèmes de cohérence des données. Ce n'est pas toujours le cas, mais le plus souvent, c'est comme ça que ça finit. Principalement parce que les programmeurs ne voient pas venir cette épave de train et ne parviennent pas à coder défensivement contre elle. De plus, cela finit souvent par montrer que la flexibilité "infinie" n'est vraiment pas nécessaire; c'est une très mauvaise "odeur" lorsque l'équipe de développement reçoit une spécification qui dit "Mon Dieu, je n'ai aucune idée du type de données qu'ils vont mettre ici, alors laissez-les mettre WHATEVER" ... et les utilisateurs finaux sont très bien avoir des types d'attributs prédéfinis qu'ils peuvent utiliser (codez un numéro de téléphone générique et laissez-les en créer - cela est trivial dans un système bien normalisé et maintient la flexibilité et l'intégrité!)
Si vous avez une très bonne équipe de développement et que vous êtes intimement conscient des problèmes que vous devrez surmonter avec cette conception, vous pouvez réussir à coder un puits conçu, pas terriblement buggy système. La plupart du temps.
Mais pourquoi commencer avec des chances si élevées contre vous?
Tu ne me crois pas? Google "One True Lookup Table" ou "conception de table unique". Quelques bons résultats: http://asktom.Oracle.com/pls/asktom/f?p=100:11:0::::P11_QUESTION_ID:10678084117056
http://thedailywtf.com/Comments/Tom_Kyte_on_The_Ultimate_Extensibility.aspx?pg=
http://www.dbazine.com/ofinterest/oi-articles/celko22
http://thedailywtf.com/Comments/The_Inner-Platform_Effect.aspx?pg=2
Un champ xml fortement typé dans MSSQL a fonctionné pour nous.
Comme certains l'ont dit, ne faites cela que si vous n'avez pas d'autre choix. Un cas où cela est nécessaire est si vous vendez un produit standard qui doit permettre aux utilisateurs d'enregistrer des données personnalisées. Le produit de mon entreprise entre dans cette catégorie.
Si vous devez autoriser vos clients à le faire, voici quelques conseils:
- Créez un outil d'administration robuste pour effectuer les modifications de schéma et ne permettez pas que ces modifications soient effectuées d'une autre manière.
- Faites-en une fonction administrative; ne permettez pas aux utilisateurs normaux d'y accéder.
- Enregistrez chaque détail de chaque modification de schéma. Cela vous aidera à déboguer les problèmes et vous donnera également des données CYA si un client fait quelque chose de stupide.
Si vous pouvez faire ces choses avec succès (en particulier la première), alors l'une des architectures que vous avez mentionnées fonctionnera. Ma préférence est de modifier dynamiquement les objets de base de données, car cela vous permet de profiter des fonctionnalités de requête de votre SGBD lorsque vous accédez aux données stockées dans les champs personnalisés. Les trois autres options nécessitent que vous chargiez de gros morceaux de données, puis effectuiez la plupart de votre traitement de données en code.
J'ai une exigence similaire et j'ai décidé d'utiliser le schéma sans MongoDB .
MongoDB (de "humongous") est une base de données orientée document, open source, évolutive, haute performance, sans schéma écrite en langage de programmation C++. (Wikipédia)
Points forts:
Lowdarks (choses que vous devez comprendre, afin que vous puissiez utiliser correctement mongo):
Je l'ai fait dans un vrai projet:
La base de données se composait d'une table avec un champ qui était un tableau de 50. Il y avait un index 'Word' dessus. Toutes les données étaient sans type, donc l '"index Word" a fonctionné comme prévu. Les champs numériques étaient représentés sous forme de caractères et le tri réel avait été effectué côté client. (Il est toujours possible d'avoir plusieurs champs de tableau pour chaque type de données si nécessaire).
Le schéma de données logiques pour les tables logiques était contenu dans la même base de données avec des lignes de table de type différent (le premier élément du tableau). Il a également pris en charge la gestion des versions simple dans le style de copie sur écriture en utilisant le même champ "type".
Avantages:
Désavantages:
Et maintenant, je pense que la prochaine étape pourrait être de mettre en œuvre une telle base de données au niveau du système de fichiers. Cela pourrait être relativement facile.
L'intérêt d'avoir une base de données relationnelle est de garder vos données en sécurité et cohérentes. Dès que vous autorisez les utilisateurs à modifier le schéma, votre intégrité des données s'en va ...
Si votre besoin est de stocker des données hétérogènes, par exemple comme un scénario CMS, je suggérerais de stocker du XML validé par un XSD dans une rangée. Bien sûr, vous perdez les performances et les capacités de recherche faciles, mais c'est un bon compromis à mon humble avis.
Depuis 2016, oubliez XML! Utilisez JSON pour stocker le sac de données non relationnel, avec une colonne correctement typée comme backend. Vous ne devriez normalement pas avoir besoin d'interroger par valeur à l'intérieur du sac, ce qui sera lent même si de nombreuses bases de données SQL contemporaines comprennent nativement JSON.
Pour moi, ce que vous voulez vraiment, c'est une sorte de "méta-schéma", un schéma de base de données qui est capable de décrire un schéma flexible pour stocker les données réelles. Les modifications de schéma dynamiques sont délicates et ne sont pas quelque chose avec quoi vous voulez jouer, surtout pas si les utilisateurs sont autorisés à effectuer la modification.
Vous n'allez pas trouver une base de données plus adaptée à cette tâche que toute autre, donc votre meilleur pari est simplement d'en sélectionner une en fonction d'autres critères. Par exemple, quelle plateforme utilisez-vous pour héberger la base de données? Dans quelle langue l'application est-elle écrite? etc
Pour clarifier ce que je veux dire par "méta-schéma":
CREATE TABLE data (
id INTEGER NOT NULL AUTO_INCREMENT,
key VARCHAR(255),
data TEXT,
PRIMARY KEY (id)
);
Il s'agit d'un exemple très simple, vous auriez probablement quelque chose de plus spécifique à vos besoins (et, espérons-le, un peu plus facile à travailler), mais il sert à illustrer mon propos. Vous devez considérer que le schéma de la base de données lui-même est immuable au niveau de l'application; tout changement structurel doit se refléter dans les données (c'est-à-dire l'instanciation de ce schéma).
Je sais que les modèles indiqués dans la question sont utilisés partout dans les systèmes de production. Un assez grand est utilisé dans une grande université/institution d'enseignement pour laquelle je travaille. Ils utilisent spécifiquement l'approche de table longue et étroite pour cartographier les données recueillies par de nombreux systèmes d'acquisition de données variés.
En outre, Google a récemment publié son protocole de partage de données interne, tampon de protocole, en tant qu'open source via son site de code. Un système de base de données calqué sur cette approche serait très intéressant.
Vérifiez les points suivants:
Je pense que l'approche EAV est la meilleure approche, mais elle a un coût élevé
Wikipedia a une excellente vue d'ensemble de l'espace problématique:
http://en.wikipedia.org/wiki/Entity%E2%80%93attribute%E2%80%93value_model
Je sais que c'est un vieux sujet, mais je suppose qu'il ne perd jamais de son actualité. Je développe quelque chose comme ça en ce moment. Voici mon approche. J'utilise un paramètre de serveur avec MySQL, Apache, PHP et Zend Framework 2 comme cadre d'application, mais cela devrait fonctionner aussi bien avec tout autre paramètre.
Voici un guide d'implémentation simple, vous pouvez le faire évoluer vous-même plus loin.
Vous devrez implémenter votre propre interpréteur de langage de requête, car le SQL efficace serait trop compliqué.
Exemple:
select id, password from user where email_address = "[email protected]"
La disposition physique de la base de données:
'Spécifications' du tableau: (doit être mis en cache dans votre couche d'accès aux données)
'Articles' du tableau:
Contenu des "spécifications" du tableau:
Contenu des éléments du tableau:
La traduction de l'exemple dans notre propre langage de requête:
select id, password from user where email_address = "[email protected]"
à SQL standard ressemblerait à ceci:
select
parent_id, -- user id
data -- password
from
items
where
spec_id = 3 -- make sure this is a 'password' item
and
parent_id in
( -- get the 'user' item to which this 'password' item belongs
select
id
from
items
where
spec_id = 1 -- make sure this is a 'user' item
and
id in
( -- fetch all item id's with the desired 'email_address' child item
select
parent_id -- id of the parent item of the 'email_address' item
from
items
where
spec_id = 2 -- make sure this is a 'email_address' item
and
data = "[email protected]" -- with the desired data value
)
)
Vous devrez avoir le tableau des spécifications mis en cache dans un tableau associatif ou une table de hachage ou quelque chose de similaire pour obtenir les spec_id à partir des noms de spécifications. Sinon, vous devrez insérer un peu plus de surcharge SQL pour obtenir le spec_id à partir des noms, comme dans cet extrait:
Mauvais exemple, ne l'utilisez pas, évitez cela, cachez plutôt le tableau des spécifications!
select
parent_id,
data
from
items
where
spec_id = (select id from specs where name = "password")
and
parent_id in (
select
id
from
items
where
spec_id = (select id from specs where name = "user")
and
id in (
select
parent_id
from
items
where
spec_id = (select id from specs where name = "email_address")
and
data = "[email protected]"
)
)
J'espère que vous comprenez l'idée et pouvez déterminer par vous-même si cette approche est réalisable pour vous.
Prendre plaisir! :-)
Dans le passé, j'ai choisi l'option C - Création d'un tableau "long et étroit" qui stocke les valeurs de colonnes dynamiques sous forme de lignes qui doivent ensuite être pivotées pour créer un ensemble de lignes "court et large" contenant toutes les valeurs d'une entité spécifique.. Cependant, j'utilisais un ORM, et cela rendait vraiment les choses douloureuses. Je ne peux pas penser à la façon dont vous le feriez dans, disons, LinqToSql. Je suppose que je devrais créer une table de hachage pour référencer les champs.
@Skliwz: Je suppose qu'il est plus intéressé à autoriser les utilisateurs à créer des champs définis par l'utilisateur.
Sur le wiki c2.com, l'idée de "Dynamic Relational" a été explorée. Vous N'AVEZ PAS besoin d'un DBA: les colonnes et les tables sont en création sur écriture, sauf si vous commencez à ajouter des contraintes pour le faire agir plus comme un SGBDR traditionnel: à mesure qu'un projet arrive à maturité, vous pouvez le "verrouiller" de manière incrémentielle.
Conceptuellement, vous pouvez considérer chaque ligne comme une instruction XML. Par exemple, un enregistrement d'employé peut être représenté comme suit:
<employee lastname="Li" firstname="Joe" salary="120000" id="318"/>
Cela n'implique pas qu'il doit être implémenté en XML, c'est juste une conceptualisation pratique. Si vous demandez une colonne non existante, telle que "SELECT madeUpColumn ...", elle est traitée comme vide ou nulle (sauf si des contraintes supplémentaires l'interdisent). Et il est possible d'utiliser SQL , bien qu'il faille faire attention aux comparaisons en raison du modèle de type implicite. Mais à part la gestion des types, les utilisateurs d'un système relationnel dynamique se sentiraient comme chez eux car ils peuvent tirer parti de la plupart de leurs connaissances existantes en SGBDR. Maintenant, si quelqu'un voulait simplement le construire ...
ElasticSearch. Vous devez en tenir compte en particulier si vous traitez avec des ensembles de données que vous pouvez partitionner par date, vous pouvez utiliser JSON pour vos données et ne sont pas déterminés à utiliser SQL pour récupérer les données.
ES déduit votre schéma pour tout nouveau champ JSON que vous envoyez, soit automatiquement, avec des astuces, soit manuellement que vous pouvez définir/modifier par une seule commande HTTP ("mappages"). Bien qu'il ne prenne pas en charge SQL, il possède de grandes capacités de recherche et même des agrégations.