web-dev-qa-db-fra.com

Le cadre d'agrégation Mongodb est-il plus rapide que la carte / réduire?

Le cadre d'agrégation introduit dans mongodb 2.2, a-t-il des améliorations de performances spéciales par rapport à la carte/réduire?

Si oui, pourquoi et comment et combien?

(J'ai déjà fait un test par moi-même et les performances étaient presque les mêmes)

53
Taha Jahangir

Chaque test que j'ai personnellement exécuté (y compris en utilisant vos propres données) montre que le cadre d'agrégation est plusieurs fois plus rapide que la réduction de la carte, et généralement un ordre de grandeur plus rapide.

Je prends juste 1/10e des données que vous avez publiées (mais plutôt que de vider le cache du système d'exploitation, de réchauffer le cache en premier - parce que je veux mesurer les performances de l'agrégation, et non pas le temps qu'il faut pour parcourir les données), j'ai obtenu ceci:

MapReduce: 1,058ms
Cadre d'agrégation: 133 ms

Suppression de la correspondance $ du cadre d'agrégation et de {query:} de mapReduce (car les deux utiliseraient simplement un index et ce n'est pas ce que nous voulons mesurer) et regroupement de l'ensemble de données par clé2, j'ai obtenu:

Réduction de la carte: 18 803 ms
Cadre d'agrégation: 1 535 ms

Celles-ci sont très conformes à mes expériences précédentes.

63
Asya Kamsky

Ma référence:

== Génération de données ==

Générez facilement 4 millions de lignes (avec python) avec environ 350 octets. Chaque document a ces clés:

  • key1, key2 (deux colonnes aléatoires pour tester l'indexation, une avec une cardinalité de 2000 et une avec une cardinalité de 20)
  • longdata: une longue chaîne pour augmenter la taille de chaque document
  • valeur: un simple nombre (const 10) pour tester l'agrégation

db = Connection('127.0.0.1').test # mongo connection
random.seed(1)
for _ in range(2):
    key1s = [hexlify(os.urandom(10)).decode('ascii') for _ in range(10)]
    key2s = [hexlify(os.urandom(10)).decode('ascii') for _ in range(1000)]
    baddata = 'some long date ' + '*' * 300
    for i in range(2000):
        data_list = [{
                'key1': random.choice(key1s),
                'key2': random.choice(key2s),
                'baddata': baddata,
                'value': 10,
                } for _ in range(1000)]
        for data in data_list:
            db.testtable.save(data)

== Tests ==

J'ai fait quelques tests, mais un suffit pour comparer les résultats:

REMARQUE: le serveur est redémarré et le cache du système d'exploitation est nettoyé après chaque requête, pour ignorer l'effet de la mise en cache.

QUERY: agréger toutes les lignes avec key1=somevalue (Environ 200 000 lignes) et additionner value pour chaque key2

  • cartographier/réduire 10,6 s
  • augmenter 9.7 sec
  • groupe 10,3 s

requêtes:

cartographier/réduire:

db.testtable.mapReduce(function(){emit(this.key2, this.value);}, function(key, values){var i =0; values.forEach(function(v){i+=v;}); return i; } , {out:{inline: 1}, query: {key1: '663969462d2ec0a5fc34'} })

agrégat:

db.testtable.aggregate({ $match: {key1: '663969462d2ec0a5fc34'}}, {$group: {_id: '$key2', pop: {$sum: '$value'}} })

groupe:

db.testtable.group({key: {key2:1}, cond: {key1: '663969462d2ec0a5fc34'}, reduce: function(obj,prev) { prev.csum += obj.value; }, initial: { csum: 0 } })

7
Taha Jahangir