2010-11-08 5 views
84

J'essaie de trouver l'équivalent des clés et des index étrangers dans les bases de données NoSQL KVP ou Document. Comme il n'y a pas de tables pivotantes (pour ajouter des clés marquant une relation entre deux objets), je suis vraiment perplexe quant à la façon dont vous seriez capable de récupérer des données d'une manière qui serait utile pour les pages Web normales.Comment suivez-vous les relations d'enregistrement dans NoSQL?

Dites que j'ai un utilisateur, et cet utilisateur laisse beaucoup de commentaires partout sur le site. La seule façon que je peux penser à garder une trace de ce que les utilisateurs des commentaires est à

  1. Intégrer eux dans l'objet utilisateur (qui semble tout à fait inutile)
  2. Créer et maintenir une valeur user_id:comments qui contient une liste de chaque commentaire de clé [commentaire: 34, commentaire: 197, etc ...] afin que je puisse les chercher au besoin.

Cependant, en prenant le deuxième exemple, vous allez bientôt frapper un mur de briques lorsque vous l'utilisez pour le suivi d'autres choses comme une clé appelée « active_comments » qui pourrait contenir 30 millions ids dans ce qui en fait coûte une tonne à interroger chaque page juste pour connaître quelques commentaires actifs récents. Il serait également très enclin à conditions de course car de nombreuses pages pourraient essayer de le mettre à jour en même temps.

Comment puis-je suivre des relations comme les suivantes dans une base de données NoSQL?

  • Tous les commentaires
  • d'un utilisateur Tous les commentaires actifs
  • Tous les messages marqués avec [mot clé]
  • Tous les étudiants dans un club - ou tous les clubs un étudiant est en

Ou est-ce que j'y pense incorrectement?

+0

Il n'y a pas une seule façon de le faire dans les bases de données NoSQL, cette question est plutôt un parent à demander comment je pourrais suivre les relations dans les programmes C. – stonemetal

+3

Wow, alors je suppose que le battage autour de NoSQL remplaçant RDBMS est impossible. – Xeoncross

+10

Oui, NoSQL est définitivement overhyped. Je ne dis pas que les nouvelles technologies ne sont pas utiles dans les bonnes circonstances, mais il est ridicule de penser qu'elles remplaceront le SGBDR. Voir http://en.wikipedia.org/wiki/Hype_cycle –

Répondre

124

Toutes les réponses sur la façon de stocker de nombreux à plusieurs associations de la « manière NoSQL » réduire à la même chose: stocker des données de manière redondante.

Dans NoSQL, vous ne concevez pas votre base de données en fonction des relations entre les entités de données. Vous concevez votre base de données en fonction des requêtes que vous exécuterez contre elle. Utilisez les mêmes critères que vous utiliseriez pour dénormaliser une base de données relationnelle: s'il est plus important que les données soient cohérentes (pensez aux valeurs dans une liste séparée par des virgules au lieu d'une table normalisée), faites-le de cette façon. Mais ceci optimise inévitablement pour un type de requête (par exemple les commentaires d'un utilisateur pour un article donné) au détriment d'autres types de requêtes (commentaires pour tout article d'un utilisateur donné). Si votre application a besoin que les deux types de requêtes soient également optimisés, vous ne devez pas les dénormaliser. De même, vous ne devez pas utiliser une solution NoSQL si vous avez besoin d'utiliser les données de manière relationnelle.

Avec la dénormalisation et la redondance, il existe un risque de désynchronisation des ensembles de données redondants. C'est ce qu'on appelle une anomalie . Lorsque vous utilisez une base de données relationnelle normalisée, le SGBDR peut empêcher les anomalies. Dans une base de données dénormalisée ou dans NoSQL, il vous incombe d'écrire le code de l'application pour éviter les anomalies.

On pourrait penser que ce serait génial pour une base de données NoSQL de faire le dur travail de prévention des anomalies pour vous. Il y a un paradigme qui peut le faire - le paradigme relationnel.

+11

"vous ne devriez pas utiliser une solution NoSQL si vous avez besoin d'utiliser les données de manière relationnelle" - Alors, comment les autres exécutant NoSQL s'en tirent-ils? Comment pouvez-vous connaître toutes les façons dont vous allez interroger les données lorsque vous concevez votre application pour la première fois? Exemple de Fox, je pourrais vouloir des commentaires récents, des commentaires par utilisateur, des commentaires par étiquette, des commentaires pour un poste donné, des commentaires marqués comme spam, des commentaires actifs, des commentaires les mieux notés, etc ... – Xeoncross

+7

Exactement - il n'y a pas une telle chose comme " ça marche "comme les avocats de NoSQL aiment à le prétendre. Soit vous faites un tas d'analyses à l'avance pour votre modélisation de données relationnelles, soit vous faites un tas d'analyses à l'avance pour vos requêtes prioritaires, ou vous effectuez une refactoring coûteuse tout au long du projet en découvrant quelles parties de votre conception n'a pas eu assez d'analyse à l'avant. –

+0

@Xeoncross Je comprends aussi ce numéro. Jetez un oeil aux index secondaires. Généralement, NoSQL crée des index secondaires pour répondre à différents cas d'utilisation métier. Cependant, un nombre inférieur d'index secondaires sont préférés. –

4
  1. utilisateur: userid: commentaires est une approche raisonnable - penser comme l'équivalent d'un index de colonne dans SQL, avec l'exigence supplémentaire que vous ne pouvez pas interroger sur des colonnes non indexées.

  2. C'est ici que vous devez réfléchir à vos besoins. Une liste de 30 millions d'articles n'est pas déraisonnable parce qu'elle est lente, mais parce qu'il est impossible de tout faire avec. Si votre véritable condition est d'afficher des commentaires récents, il vaut mieux garder une liste très courte qui est mise à jour chaque fois qu'un commentaire est ajouté - rappelez-vous que NoSQL n'a aucune exigence de normalisation. Les conditions de course sont un problème avec les listes dans un magasin de valeurs de clés de base, mais généralement, votre plate-forme prend en charge les listes correctement, vous pouvez faire quelque chose avec des verrous ou vous ne vous souciez pas des mises à jour échouées.

  3. même que pour les commentaires des utilisateurs - créer un mot-clé d'index: messages

  4. Plus du même - probablement une liste des clubs comme une propriété de l'étudiant et un index sur ce champ pour obtenir tous les membres d'un club

+0

Donc, fondamentalement tout a juste besoin de listes? On dirait qu'il devrait y avoir une approche plus sophistiquée que le simple suivi manuel des chaînes d'identifiants. Pour un, vous pouvez seulement aller si loin avant qu'ils deviennent trop grands pour être utiles. Là encore, les principaux projets d'affiches de la technologie NoSQL (MongoDB, CouchDB, Membase, etc.) sont tous de nouveaux projets, alors je dois peut-être leur laisser plus de temps pour trouver un meilleur moyen de suivre les relations. – Xeoncross

+0

Si vous utilisez NoSQL (banques de données non relationnelles AKA), vous devez cesser de penser en termes relationnels. L'approche utilisée diffère selon les plateformes, mais l'idée de base que vous devez gérer les index est assez universelle. Les exemples de relation que vous avez donnés sont modélisés de deux manières différentes dans NoSQL: 1) Stockage - contrairement à SQL, les colonnes peuvent avoir des valeurs multiples/complexes, donc l'objet enfant n'est qu'une partie de l'objet parent. 2) Recherche - Vos longues listes sont en fait une exigence pour la recherche, ce qui signifie l'indexation - vous pouvez utiliser une simple liste personnalisée ou un moteur de recherche plus complet. –

3

l'approche CouchDB suggèrent d'émettre des classes appropriées de substance en phase de carte et résumer en réduire .. vous pouvez mapper tous les commentaires et émettre 1 pour l'utilisateur donné et imprimer plus tard seuls.Il faudrait cependant beaucoup de stockage sur disque pour construire des vues persistantes de toutes les données traçables dans couchDB. btw ils ont aussi cette page wiki sur les relations: http://wiki.apache.org/couchdb/EntityRelationship.

Riak d'autre part a un outil pour construire des relations. C'est un lien. Vous pouvez entrer l'adresse d'un document lié (ici un commentaire) au document 'root' (ici le document utilisateur). Il a un tour. S'il est distribué, il peut être modifié en même temps dans de nombreux endroits. Cela provoquera des conflits et par conséquent un énorme arbre d'horloge vectoriel:/..pas si mauvais, pas si bon.

Riak a également un autre «mécanisme». Il possède un espace de nom de clé à 2 couches, appelé bucket and key. Ainsi, par exemple des étudiants, si nous avons le club A, B et C et étudiant Studentx, studenty vous pouvez maintenir suivant convention:

{ Key = {ClubA, StudentX}, Value = true }, 
{ Key = {ClubB, StudentX}, Value = true }, 
{ Key = {ClubA, StudentY}, Value = true } 

et de lire ce qui concerne seulement les clés de la liste dans des seaux donnés. Qu'est-ce qui ne va pas avec ça? C'est sacrément lent. La liste des buckets n'a jamais été une priorité pour riak. Il devient de mieux en mieux. BTW vous ne perdez pas de mémoire car cet exemple {true} peut être lié à un seul profil complet de StudentX ou Y (ici les conflits ne sont pas possibles).

Comme vous le voyez NoSQL! = NoSQL. Vous devez examiner une implémentation spécifique et la tester par vous-même. Mentionné avant que les magasins de colonnes ressemblent à un bon ajustement pour les relations .. mais tout dépend de vos besoins A et C et P;) Si vous n'avez pas besoin de A et que vous avez moins de Peta octets, laissez-le, allez-y. MySql ou Postgres.

bonne chance

+1

Riak a récemment publié la version 1.0, qui ajoute la prise en charge des index secondaires lors de l'utilisation du backend LevelDB. Caractéristique très précieuse. –

0

Je pense que RavenDB offre une bonne solution à ce problème avec l'indexation. Les informations sur la page principale http://ravendb.net/ explique assez bien le concept que vous pourriez probablement créer quelque chose d'analogue pour votre technologie.

1

Vous avez

"user": { 
    "userid": "unique value", 
    "category": "student", 
    "metainfo": "yada yada yada", 
    "clubs": ["archery", "kendo"] 
} 

"comments": { 
    "commentid": "unique value", 
    "pageid": "unique value", 
    "post-time": "ISO Date", 
    "userid": "OP id -> THIS IS IMPORTANT" 
} 

"page": { 
    "pageid": "unique value", 
    "post-time": "ISO Date", 
    "op-id": "user id", 
    "tag": ["abc", "zxcv", "qwer"] 
} 

Eh bien dans une base de données relationnelle de la chose normale à faire serait en tête-à-plusieurs est de normaliser les données. C'est la même chose que dans une base de données NoSQL. Il suffit d'indexer les champs avec lesquels vous allez chercher l'information.

Par exemple, les indices importants pour vous sont

  • Comment.UserID
  • Comment.PageID
  • Comment.PostTime
  • Page.Tag []

Si vous utilisent NosDB (A .NET based NoSQL Database with SQL support) vos requêtes seront comme

SELECT * FROM Comments WHERE userid = ‘That user’; 

SELECT * FROM Comments WHERE pageid = ‘That user’; 

SELECT * FROM Comments WHERE post-time > DateTime('2016, 1, 1'); 

SELECT * FROM Page WHERE tag = 'kendo' 

Vérifiez tous les types de requêtes pris en charge à partir de leur SQL cheat sheet ou de leur documentation.