2011-01-24 7 views
3

Nous avons une application qui pourrait grandement bénéficier de l'utilisation d'un magasin de données basé sur des documents comme CouchDB. Mais nous avons un cas d'utilisation de requête que j'ai du mal à implémenter avec Map Reduce.Stratégie pour les requêtes de prédicat arbitraires dans Couchdb

Nos documents contiennent vraiment que deux types de données:

  1. attributs numériques
  2. attributs booléens

Le booléen attribue marque essentiellement un document comme appartenant à un ou plusieurs ensembles non exclusifs . Les attributs numériques auront toujours seulement besoin d'être additionnés. Une façon de structurer le document comme celui-ci:

{ 
    "id": 3123123, 
    "attr": {"x": 2, "y": 4, "z": 6}, 
    "sets": ["A", "B", "C"] 
} 

Avec cette structure, il est facile de travailler x total, y, les valeurs z pour les ensembles A, B et C, mais cela devient plus compliqué quand vous voulez Pour voir les agrégats pour les intersections comme A

Dans ce petit cas, je pourrais émettre des clés pour toutes les permutations de ABC ("A, B, C, AB, AC, BC, ABC"), mais je suis inquiet de la façon dont cela va évoluer. Nos documents pourraient appartenir à une combinaison de 80 ensembles et il est dirigé par une interface utilisateur qui peut construire n'importe quelle combinaison imaginable d'entre eux. Je suis enclin à penser que ce n'est pas un travail pour un CouchDB, et peut-être que MongoDB ou quelque chose d'autre serait mieux adapté à ce problème.

Est-ce que je manque quelque chose?

Répondre

3

Une structure de données qui peut efficacement calculer et mettre en cache toutes ces valeurs va être assez complexe. Je ne suis pas certain que n'importe quel système de base de données est capable de faire cela sans itération sur des sous-ensembles. Intersection est une opération notoirement difficile, et CouchDB n'a vraiment rien de disponible pour gérer l'intersection correctement.

Comme vous ont correctement identifié, émettant toutes les permutations (sous-ensembles, pour être précis) va être un porc de mémoire car il va encore multiplier vos articles par un facteur énorme (2 n paires clé-valeur pour n ensembles). Vous pouvez réduire cela en regroupant les préfixes (la structure de clé CouchDB vous permet de récupérer les valeurs pour ["A"] et ["A","B"] lorsque vous émettez pour ["A","B","C"] en utilisant l'option de niveau groupe) mais seulement par un facteur de 2 (2 n-1 valeur-clé paires pour n ensembles). Donc, si vos objets ont en moyenne trois ensembles associés, tout ira bien (4 paires valeur/clé au lieu de 3), mais quatre ensembles associés sont plus lourds (8 au lieu de 4) et cinq commencent devenir agaçant (16 au lieu de 5). Cela rend également les éléments avec de nombreux ensembles associés vulnérables aux problèmes de performances (un élément de 10 ensembles créerait plus de 500 paires clé-valeur). Une approche intermédiaire consisterait à émettre des clés d'une longueur maximale de quatre ensembles (il ne fait que doubler la mémoire requise) et à exécuter un traitement côté application lorsqu'une intersection plus profonde est requise (saisir tous les éléments sans réduction, exécuter la réduction dans l'application). Avec un peu de chance, le nombre d'objets concernés sera plus petit - si ce n'est pas le cas, vous pouvez toujours utiliser la taille maximale pour sacrifier plus de mémoire pour plus de performance.Une approche inverse consisterait à demander à l'application de mettre à jour 2 n totaux lorsque chaque document est inséré/mis à jour (en récupérant tous les documents «totaux» correspondant à un sous-ensemble de l'élément actuel). Ces totaux seraient stockés dans une base de données différente et seraient interrogés par clé. Cette approche est préférable si vous pouvez vous permettre de mettre à jour des totaux à la volée (ou si votre architecture vous permet de les mettre à jour en écoutant les mises à jour dans la base de données principale), car les requêtes sont rapides.

+0

Merci Victor - à ce stade, je me penche vers MongoDB avec ses index multi-clés. Sinon, une approche que je pourrais essayer avec Couch serait de stocker des comptes de correspondance et d'utiliser le plus petit ensemble comme base pour une réduction côté client. Ou, comme vous le dites, peut-être prendre cela à deux sous-ensembles de combinaison. –

Questions connexes