0

Mon équipe écrit une application avec GAE (Java) qui m'a amené à remettre en question l'évolutivité de la modélisation des relations d'entités (spécifiquement plusieurs-à-plusieurs) dans des bases de données orientées objet comme BigTable. La solution préférée pour modéliser des relations un-à-plusieurs et plusieurs-à-plusieurs sans propriétaire dans la banque de données App Engine (voir Entity Relationships in JDO) semble être une liste de clés. Cependant, Google met en garde:Est-ce que la modélisation de relations à l'échelle infinie dans NoSQL/BigTable (GAE) est possible?

« Il y a quelques limites à la mise en œuvre de nombreux à plusieurs relations ainsi d'abord, vous devez explicitement les valeurs du côté de la collection où la liste est stockée depuis. tout ce que vous ont disponibles sont des objets clés. un autre plus important est que vous voulez éviter de stocker des listes trop grandes de clés ... »

En parlant de listes trop grandes de clés, si vous essayez de modélisez de cette façon et supposez que vous stockez o ne Long pour chaque clé puis avec une limite par entité de 1 Mo, le nombre maximum théorique de relations par entité est ~ 130k. Pour une plateforme dont l'avantage principal est la scalabilité, ce n'est vraiment pas beaucoup de relations. Nous examinons maintenant des entités pouvant être fragmentées qui nécessitent plus de 130 000 relations.

Une approche différente (Modèle de relation) est décrite dans l'article Modeling Entity Relationships dans le cadre de la série Maîtriser la banque de données dans les ressources du développeur AppEngine. Cependant, même ici Google met en garde contre les performances des modèles relationnels.

« Cependant, vous devez être très prudent, car traversant les connexions d'une collection, il faudra plus d'appels à la datastore Utilisez ce genre de beaucoup -to-many relation seulement lorsque vous avez vraiment besoin de , et faites-le avec soin pour les performances de votre application. "

Alors maintenant vous demandez: 'Pourquoi avez-vous besoin de plus de 130k relations par entité?' Eh bien, je suis content que vous ayez demandé. Prenons, par exemple, une application CMS dire 1 million d'utilisateurs (Hey je peux rêver non ?!)

Les utilisateurs peuvent télécharger le contenu et le partager avec: 1. publics 2. personnes 3. Groupes 4 Maintenant, quelqu'un se connecte et accède à un tableau de bord qui affiche les nouveaux téléchargements des personnes auxquelles il est connecté dans n'importe quel groupe. Ce tableau de bord doit inclure du contenu public et du contenu partagé spécifiquement avec cet utilisateur ou un groupe dont cet utilisateur est membre. Pas trop mal non? Fouillons dedans.

public class Content { 
    private Long id; 
    private Long authorId; 
    private List<Long> sharedWith; //can be individual ids or group ids 
} 

Maintenant, ma requête pour obtenir tout un identifiant est autorisé à voir pourrait ressembler à ceci:

List<Long> idsThatGiveMeAccess = new ArrayList<Long>(); 
idsThatGiveMeAccess.add(myId); 
idsThatGiveMeAccess.add(publicId); //Let's say that sharing with 0L makes it public 
for (Group g : groupsImIn) 
    idsThatGiveMeAccess.add(g.getId()); 

List<Long> authorIdsThatIWantToSee = new ArrayList<Long>(); 
//Add a bunch of authorIds 

Query q = new Query("Content") 
      .addFilter("authorId", Query.FilterOperator.IN, authorIdsThatIWantToSee) 
      .addFilter("sharedWith", Query.FilterOperator.IN, idsThatGiveMeAccess); 

Il est évident que je l'ai déjà brisé plusieurs règles. A savoir, l'utilisation de deux filtres IN va exploser. Même un seul filtre IN à n'importe quelle taille approchant les limites dont nous parlons exploserait. En dehors de tout cela, disons que je veux limiter et feuilleter les résultats ... non non! Vous ne pouvez pas faire cela si vous utilisez un filtre IN.Je ne vois pas de moyen de faire cette opération dans une seule requête - ce qui signifie que vous ne pouvez pas la paginer sans un traitement de lecture intensif et la gestion de plusieurs curseurs.

Voici donc les outils auxquels je peux penser pour cela: dénormalisation, sharding ou relations. Cependant, même avec ces concepts, je ne vois pas comment il est possible de modéliser ces données d'une manière qui puisse évoluer. De toute évidence, c'est possible. Google et les autres le font tout le temps. Je ne peux pas voir comment. Quelqu'un peut-il faire la lumière sur la façon de modéliser ceci ou me diriger vers de bonnes ressources pour le contrôle d'accès de style cms basé sur NoSQL DB?

Répondre

1

de stocker une liste d'ID en tant qu'échelle de propriété Wont. Pourquoi ne pas simplement stocker un nouvel objet pour chaque nouvelle relation? (Comme en sql). Cet objet stockera pour vos cms deux propriétés: L'ID de l'élément partagé et l'ID de l'utilisateur. Si c'est partagé avec 1000 utilisateurs, vous en aurez 1000. L'interroger pour un utilisateur donné est trivial. La liste des autorisations pour un élément donné ou une liste de ce qu'un utilisateur a partagé avec eux est également facile.

Questions connexes