Mon projet actuel consiste essentiellement à exécuter le système de gestion des documents de l'usine.
Cela dit, il y a des rides (surprise, surprise). Bien que certaines rides soient assez spécifiques au projet, je pense qu'il y a des observations générales et des questions qui n'ont pas eu de réponse canonique (que je pourrais trouver, de toute façon) et qui sont applicables à un domaine de problème plus large . Il y en a beaucoup ici et je ne suis pas sûr que cela corresponde bien au format StackExchange Q&A, mais je pense que c'est a) une question à laquelle il est possible de répondre et b) suffisamment non spécifique pour que cela puisse bénéficier à la communauté. Certaines de mes considérations me sont spécifiques, mais je pense que la question pourrait être utile à quiconque confronté à la décision de SQL vs NoSQL vs les deux.
L'application Web que nous construisons contient des données de nature clairement relationnelle ainsi que des données orientées document. Nous aimerions avoir notre gâteau et le manger aussi.
TL; DR: Je pense que le numéro 5 ci-dessous réussit le test de l'odorat. Le faites vous? Quelqu'un a-t-il de l'expérience avec une telle intégration de SQL et NOSQL dans une seule application? J'ai essayé de lister toutes les approches possibles de cette classe de problèmes ci-dessous. Ai-je manqué une alternative prometteuse?
Essentiellement, il s'agit d'un méli-mélo de données relationnelles (vos applications Web typiques comme les utilisateurs, les groupes, etc., ainsi que les métadonnées de document que nous devrons être en mesure de découper et de dés avec des requêtes complexes en temps réel) et de données de document (par exemple les centaines de champs que nous n'avons aucun intérêt à joindre ou à interroger - notre seul cas d'utilisation pour les données sera d'afficher le document unique dans lequel elles ont été saisies).
Je voulais faire un contrôle de santé mentale (si vous vérifiez mon historique de publication, je suis assez explicite sur le fait que je ne suis pas un DBA) sur ma méthode préférée ainsi que d'énumérer toutes les options que j'ai rencontrées pour que d'autres résolvent des problèmes globalement similaires impliquant à la fois des données relationnelles et non relationnelles.
1. Une table par classe de document
Chaque classe de document obtient sa propre table, avec des colonnes pour toutes les métadonnées et données.
Avantages:
Désavantages:
2. Modélisation EAV
Il y a juste une table des champs. La modélisation Entité-Attribut-Valeur est déjà bien comprise. Je l'ai inclus pour être complet. Je ne pense pas qu'un nouveau projet démarré en 2013 irait volontairement avec une approche EAV.
Avantages:
Désavantages:
3. Utiliser les champs hstore ou json de PostgreSQL
L'un ou l'autre de ces types de champ ferait l'affaire pour stocker des données sans schéma dans le contexte d'une base de données relationnelle. La seule raison pour laquelle je ne saute pas immédiatement à cette solution est qu'elle est relativement nouvelle (introduite dans la version 8.4 donc pas ça nouveau), je n'ai aucune exposition précédente à elle et je me méfie. Cela me semble erroné précisément pour les mêmes raisons pour lesquelles je serais mal à l'aise de jeter toutes mes données Nice, facilement normalisées dans Mongo - même si Mongo peut gérer les références entre les documents.
Avantages:
Désavantages:
4. Passez au document intégral
Créez tous les documents (au sens MongoDB). Créez une collection unique de type Document
et appelez-la un jour. Importez également toutes les données périphériques (y compris les données sur les comptes d'utilisateurs, les groupes, etc.) dans Mongo. Cette solution est évidemment meilleure que la modélisation EAV mais cela me semble mal pour la même raison # 3 se sentait mal - ils ont tous les deux envie d'utiliser votre marteau comme tournevis aussi.
Avantages:
Document
et appelez-la un jour.Désavantages:
5. PostgreSQL et MongoDB
Les données relationnelles vont dans la base de données relationnelle et les données de document vont dans la base de données orientée document. La table documents
de la base de données relationnelle contient toutes les données dont nous pourrions avoir besoin pour indexer ou découper et découper ainsi qu'un MongoDB ObjectId que nous utiliserions lorsque nous aurons besoin de rechercher les valeurs réelles des champs sur les documents. Nous ne serions pas en mesure d'utiliser l'ORM ou l'administrateur intégré pour les valeurs des documents eux-mêmes, mais ce n'est pas une grosse perte puisque l'application entière est essentiellement une interface d'administration pour les documents et nous aurions probablement dû personnaliser cette partie spécifique de l'ORM à un degré inacceptable pour le faire fonctionner comme nous en avons besoin.
Avantages:
documents
, quel que soit le nombre de classes de documents créées.Désavantages:
Quelques idées....
Généralement, on ne veut pas stocker des éléments d'informations étroitement liés dans différents systèmes. Les chances que les choses ne se synchronisent pas sont importantes et maintenant, au lieu d'un problème, vous en avez deux. Une chose que vous pouvez faire avec Mongo est de l'utiliser pour acheminer ou sortir vos données. Ma préférence est de tout garder dans PostgreSQL dans la mesure du possible. Cependant, je noterais que cela nécessite vraiment une connaissance approfondie de la programmation PostgreSQL et n'est pas destiné aux magasins qui ne souhaitent pas se consacrer à l'utilisation de fonctionnalités avancées. Je vois un ensemble d'options quelque peu différent du vôtre. Comme ma préférence n'est pas quelque chose que je vois dans la liste, je vous la donnerai.
Vous pouvez probablement séparer vos métadonnées en données communes, données requises pour les classes et données de document. À cet égard, vous auriez un tableau de catalogue général avec les informations communes de base plus un tableau par classe. Dans ce tableau, vous auriez un champ hstore, json ou xml qui stockerait le reste des données ainsi que des colonnes où vous stockez des données qui doivent être contraintes de manière significative. Cela réduirait ce que vous devez mettre dans ces tables par classe, mais vous permettrait de tirer parti des contraintes comme vous le souhaitez. Les trois options ont des problèmes différents et méritent d'être examinées séparément:
hstore est relativement limité mais aussi utilisé par beaucoup de gens. Ce n'est pas extrêmement nouveau mais c'est seulement un magasin de clés/valeurs, et est incapable de structures de données imbriquées, contrairement à json et xml.
json est assez nouveau et ne fait pas grand-chose en ce moment. Cela ne signifie pas que vous ne pouvez pas en faire beaucoup, mais vous n'allez pas en faire beaucoup hors de la boîte. Si vous le faites, vous pouvez vous attendre à faire une quantité importante de programmation, probablement dans plv8js ou, si vous voulez vous en tenir à des environnements plus anciens, plperlu ou plpython. json
est mieux pris en charge dans 9.3 bien qu'au moins dans les instantanés de développement actuels, donc quand cette version sera publiée, les choses iront mieux.
xml est le meilleur supporté des trois, avec le plus de fonctionnalités et le plus long historique de support. Là encore, c'est XML .....
Cependant, si vous décidez d'aller avec Mongo et PostgreSQL ensemble, notez que PostgreSQL prend en charge la validation en 2 phases, ce qui signifie que vous pouvez exécuter les opérations d'écriture, puis lancez PREPARE TRANSACTION
et si cela réussit, faites vos écritures atomiques en Mongo. Si cela réussit, vous pouvez alors COMMIT
dans PostgreSQL.
Vous pouvez configurer un moteur de requête tel que Presto ou Dremio pour joindre des données résidant dans MongoDB et Postgres avec une seule requête. Les deux ont des connecteurs pour chacune de ces bases de données (voir les documents ici et ici ) et proposent, respectivement, d'exécuter "SQL sur n'importe quoi" et de "joindre n'importe quoi".
Pour tester Presto, vous pouvez déployer un petit cluster sur AWS EMR avec Hadoop, Hive et Presto (ajoutez une teinte si vous ne souhaitez pas utiliser la ligne de commande), cela fonctionne à partir de la boîte - assurez-vous de suivez ces instructions pour configurer les connecteurs . Hive n'est pas strictement nécessaire, mais avec lui, vous pouvez créer des tables en utilisant le résultat des jointures entre Mongo et Postgres (consultez cette page pour des exemples). Il existe également une version payante sur le marché , qui est (soi-disant) fortement optimisée et dispose d'un essai de 30 jours.
Je n'ai pas utilisé Dremio, mais il y a aussi quelques façons simples de le déployer sur AWS, Azure ou sur site. Ils ont certains cours en ligne sur leur site Web , avec accès à un "laboratoire virtuel" que vous pouvez utiliser pour suivre les cours gratuitement.