J’ai un modèle relationel très complexe avec des règles métier des plus biscornues quand on souhaite relire quelque chose. Par exemple, pour récupérer le libellé d’un item il faut que je concatène plusieurs champs et que je fasse une ou deux conditions pour gérer des cas spécifiques.
J’ai peur que ça devienne difficile à gérer et que ça facilite énormément les erreurs de traitement à l’avenir.
J’ai envisagé les trois solutions classiques :
- dénormaliser le modèle en stockant à plat certaines données précalulées dans le SGBDR, mais il y a pas mal de choses où c’est vraiment délicat, par exemple quand un item contient une collection de données
- coder des vues complexes et des procédures stockées pour automatiser certaines actions, mais j’ai l’impression de déporter mon métier là où ça sera le plus difficile à maintenir et à développer
- ou utiliser un bête stockage orienté document et laisser tomber le relationnel, qui de toutes façons me sert assez peu sur ces données
À priori je suis plutôt parti sur la troisième solution et j’ai besoin de vos lumières pour choisir le datastore le plus adapté.
Voici mes contraintes :
- Performant (c’est pour utiliser en permanence au cœur de l’infra)
- Accessible facilement en PHP
- Stocke des données structurées (type json) avec de la hiérarchie (un document peut contenir une collection par exemple)
- Le modèle de chaque document doit être libre ou en tout cas très souple
- Sait manipuler une collection de plusieurs millions de documents (d’où la nécessité des index au point précédent)
- Sur ces millions de doc je peux faire des requêtes de type « par date de mise à jour inverse, uniquement ceux qui ont un attribut ‘toto’ à 145 et un attribut ‘tata’ à 567 » sans avoir à faire un scan de tous les documents à la requête (ce qui implique probablement des index)
- Sait gérer de la haute disponibilité (par exemple deux serveurs synchronisés en master-master)
- Simple à utiliser et administrer
- Stockage disque (donnée pérenne en cas de plantage)
- Accès réseau (la base et l’applicatif sont sur des serveurs différents)
J’ai aussi des non contraintes :
- Les écritures sont faites en batch, je n’ai pas besoin de transaction ou de lock d’écriture
- Je n’ai pas besoin de validation, typage, ou contrainte d’intégrité
- Je n’ai pas besoin de transactions
- En cas de plantage, j’accepte de perdre quelques minutes de données non écrites (mais pas de planter les anciennes données)
- J’accepte des latences jusqu’à quelques minutes entre les différents serveurs synchronisés
- Je peux prévoir à l’avance les requêtes que je vais faire (et donc construire des index dédiés)
Les bonus :
- Consommation mémoire pas trop délirante
- Outil pour faire des dump/restore
Cassandra, Voldemort, MongoDB et autres joyeusetés, je suis preneur de vos recommandations avec explications, ou simplement des liens vers des billets qui peuvent m’éclairer.
Merci à vous cher public (j’ai toujours rêvé de dire ça ;)
9 réponses à “Document store à recommander”
C’est une réponse peut être hors sujet, mais si ton seul soucis est de chercher, tu peux garder ton système de stockage actuel et indexer tes données en temps réel avec ElasticSearch.
Ça supporte pratiquement tous les points requis, même si pour des questions de performance il vaut mieux lui fournir un schéma le plus complet possible avant d’indexer (quitte à lui filer des données incomplètes). Tu peux aussi faire des queries très complexes en javascript, si les possibilités de recherche de base (assez étendues) ne te suffisent pas.
Tu viens de décrire exactement ce que fait le projet CouchDB :)
Au vu de tes contraintes, je seconde la recommandation de CouchDB.
Si tu relâches la contrainte de réplication Master-Master, et que tu acceptes une réplication Master-Slave(s), avec élection d’un nouveau Master en cas de perte du Master, tu peux aussi aller vers MongoDB.
Dans les deux cas, tu devras construire des index en fonction des requêtes que tu veux faire, mais ça se fera un peu différemment. Avec CouchDB, un index est une « vue » que tu exprimes généralement avec un petit bout de Javscript. C’est très flexible, mais un peu déroutant au début. Avec MongoDB, ça ressemble plus à ce que tu ferais avec du SQL, où tu te contentes d’ajouter un index sur une colonne.
> Cassandra, Voldemort, MongoDB
Attention c’est pas pareil :
– Cassandra : orienté colonne
– Voldemort : orienté clé/valeur
– MongoDB : orienté document (document pouvant contenir des valeurs simples – string, int, etc – ou complexes, par exemple clé/valeur)
Après, choisir n’est pas simple du tout. A priori une orienté document serait intéressante, mais même dans ce cas il y a plusieurs choix, entre autre MongoDB vs CouchDB
La première chose est donc de voir précisément quel type de stockage est intéressant. Ensuite, faut choisir dans les possibilités, sachant que beaucoup proposent une interface REST avec du Json (donc c’est accessible par le réseau, entre serveurs ou depuis le client, etc) Bon parfois il y a aussi du BSON plutôt que JSON.
Quelques liens :
* Pour comparaison de différentes solutions (et explication) : http://www.smile.fr/Livres-blancs/Culture-du-web/NoSQL
* Pour comparaison de cassandra, mongodb, couchdb, redis, riak, … http://kkovacs.eu/cassandra-vs-mongodb-vs-couchdb-vs-redis
* Comparaison MongoDB – CouchDB (en prenant en compte que c’est sur le site de MongoDB) http://www.mongodb.org/display/DOCS/Comparing+Mongo+DB+and+Couch+DB
Bon, évidemment c’est encore une réponse du type « faut voir » mais avec de quoi commencer. Dans tous les cas je dirais qu’il y a deux étapes principales : choix du type de stockage puis choix de la solution exacte.
Le problème au final c’est que NoSQL regroupe pas mal de choses assez différentes.
Et histoire de rajouter une solution beaucoup plus… heu… particulière : https://gist.github.com/2715918
En gros, comment faire de l’orienté document avec stockage json dans un PostgreSQL. Je ne suis pas sur que ça puisse répondre mais c’est une solution qui peut parfois être envisageable s’il y a déjà du postgres dans l’infra par exemple.
Pour les index, il me semble que MongoDB a ça. Voir The Little MongoDB Book par Karl Seguin (http://openmymind.net/2011/3/28/The-Little-MongoDB-Book/) et sa « comparaison » MongoDB / CouchDB : http://openmymind.net/2011/10/27/A-MongoDB-Guy-Learns-CouchDB
Comme déjà dit, ton besoin semble t’orienter naturellement vers de la base documentaire. Après, je dis « ton besoin », mais ce n’est pas réellement ton besoin que tu nous as présenté, mais plutôt tes pré-choix ;)
La bonne manière pour choisir son moteur c’est plutôt de se demander de quelle façon on manipule les données. Là tu as effectivement parler de champs dont la valeur dépend d’autres champs, mais ça à la limite c’est hors-sujet: soit c’est du côté de l’application et on se fout du mode de stockage, soit c’est pré-calculé et ce n’est qu’un champ parmi d’autres et là encore on se fout du stockage. Ce n’est pas un cas qui permet de discriminer les solutions qui s’offrent à toi.
Tu as énoncé des besoins techniques qui permettront sans doute d’éliminer certaines solutions.
Après pour le choix final, à mon avis les bonnes questions sont plutôt:
* Est-ce que j’ai besoin de sortir des statistiques à partir des documents (par exemple combien de fois tel livre a été lu, et par quel groupe) ? Comment souhaité-je remplir ces statistiques ? À quelle fréquence doivent-elles être à jour ?
* Est-ce que j’ai besoin de résoudre certaines relations (par exemple les livres par le(s) même(s) auteur(s), les livres traitant du même sujet) ? Ça permet généralement de définir en plus comment on va modéliser les données.
Bref, plutôt des questions sur la façon dont seront utilisées fonctionnellement les données, qui permettra de savoir sur quel cas se concentrer et permettra de définir le choix idéal comme étant le moteur de stockage gérant le mieux ces choix.
Cela dit ton besoin de réplication et de disponibilité semble t’orienter vers du NoSQL. Tu n’auras pas forcément envie de te retourner complètement l’esprit donc on peut virer les key/value et les bases graphes, qui obligent à changer complètement notre mode de réflexion lors de la modélisation.
Une base documentaire sera plus simple à utiliser et le modèle sera plus simple à concevoir.
Du coup on revient aux classiques MongoDB ou CouchDB (je ne t’ai donc pas plus avancé que les commentaires précédents, mais tu sais déjà un peu mieux pourquoi on arrive à ce duo ;)).
Pour résumer ce que je connais de leurs différences (les articles cités par CrEv complèteront):
* CouchDB est à mon avis bien plus complexe d’utilisation, le mode de requêtage par vue est vraiment difficile à appréhender au début, la courbe d’apprentissage est plus raide que MongoDB.
* CouchDB gère *réellement* les fichiers attachés. Ce sont des entités bien définies, et c’est plus simple à gérer que GridFS (je ne sais pas si tu as ce besoin).
* CouchDB versionne nativement les documents. C’est cool :)
Pour le reste je sais que MongoDB gère les index, qu’il a un systême de procédures stockées ultra simple (tu sauves une fonction JS dans ta base…) qui pourrait bien te servir pour tes calculs de champ composé. Je ne connais pas assez CouchDB pour te dire s’il bénéficie aussi de ces fonctionnalités ou pas.
Quelque bench simpliste
https://gist.github.com/326aa60b62a834a91cfe
https://gist.github.com/8b843d601e5e1d613c10
Pour la haute disponibilité, je ne sais pas si les Replica Set de MongoDB te conviennent…
Pour la RAM, je ne sais plus comment fonctionne CouchDB mais Mongo stock le maximum dedans (filecache géré par l’OS en fait).
Etant dénormalisée, chaque « nom de colonne » devient un nom de champ et est donc répliqué dans chaque document, d’ou une empreinte mémoire plus lourde.
Regarde entre CouchDB et MongoDB ce qui te convient le mieux (feature / suivi de l’entreprise derriere).
Le seul point noir de MongoDB est la lenteur pour avoir certaine feature : ex : https://jira.mongodb.org/browse/SERVER-831 (c’est dispo que sur un étage mais pas plus).
Ceci dit à coté ils[10gen] bossent sur d’autres features: le framework d’aggrégation, hyper simple à maintenir / travailler en équipe / debugger, bien plus simple que du Map/Reduce, du search amélioré etc…
Désolé si c’est un peu hors sujet, mais au cas où… j’ai commencé à lire un bouquin sur le sujet qui me semble vraiment pas mal pour comprendre les notions fondamentales de ces différents types de SGBD :
http://pragprog.com/book/rwdata/seven-databases-in-seven-weeks