2012-12-27 7 views
7

Ich beginne gerade mit mongo db und versuche, ein paar einfache Dinge zu machen. Ich habe meine Datenbank mit einer Sammlung von Daten gefüllt, die die Eigenschaft "item" enthält. Ich wollte Zählung versuchen, wie viel Zeit jeder Artikel in der SammlungMongoDB-Aggregation so langsam wie MapReduce?

Beispiel eines Dokuments ist:

{ "_id" : ObjectId("50dadc38bbd7591082d920f0"), "item" : "Pons", "lines" : 37 } 

So entwarf ich diese beiden Funktionen für MapReduce tun (geschrieben in Python mit pymongo)

all_map = Code("function() {" 
      " emit(this.item, 1);" 
      "}") 

all_reduce = Code("function (key, values) {" 
        " var sum = 0;" 
        " values.forEach(function(value){" 
        "  sum += value;" 
        " });" 
        " return sum;" 
        "}") 

Dies funktionierte wie ein Charme, so begann ich die Sammlung zu füllen. Bei etwa 30.000 Dokumenten dauert der Mapreduce bereits länger als eine Sekunde ... Da NoSQL über Geschwindigkeit prahlt dachte ich, ich muss etwas getan haben falsch!

Eine Frage hier bei Stack Overflow ließ mich die Aggregation Feature von Mongodb überprüfen. Also habe ich versucht, die Gruppe + sum + sort things zu verwenden. Kam mit dieser:

db.wikipedia.aggregate(
{ $group: { _id: "$item", count: { $sum: 1 } } }, 
{ $sort: {count: 1} } 
) 

Dieser Code funktioniert gut und gibt mir die gleichen Ergebnisse wie der mapreduce Satz, aber es ist genauso langsam. Mache ich etwas falsch? Muss ich wirklich andere Werkzeuge wie hadoop verwenden, um eine bessere Leistung zu erhalten?

+1

$ Gruppe kann nicht einen Index verwenden und dann nehmen Sie die vollständige Tabelle scannen und sortieren auf einem berechneten Feld, das wieder nicht einen Index verwenden kann ... hmmm ja ich denke, das könnte leicht so langsam und MR sein, werfen Sie einen Blick auf die Hinweise zu $ ​​sort: http://docs.mongodb.org/manual/reference/aggregation/#_S_sort.Wenn ich ehrlich bin, denke ich nicht, dass dies der Fehler des Tools ist, sondern mehr von der Gestaltung des Schemas, wenn Sie eine solche Abfrage in Echtzeit-Zeit benötigen – Sammaye

+0

lesen Sie dies für die Klarstellung: http: // stackoverflow.com/questions/12015064/mongodb-mapreduce-and-sorting –

+0

@Sammaye Wie Sie meine Schlusssätze lesen, werden Sie feststellen, dass ich nicht auf die Werkzeuge tanze. Ich habe noch keine Erfahrung mit NoSQL und MongoDB. Ich frage nur, was falsch ist. Wie ich mein Design verbessern kann, um dieses Ding auf den richtigen Weg zu bringen. – Arninja

Antwort

9

Ich werde eine Antwort im Grunde summieren meine Kommentare. Ich kann nicht für andere Techniker wie Hadoop sprechen, da ich noch nicht das Vergnügen hatte, Zeit für sie zu finden, aber ich kann für MongoDB sprechen.

Leider verwenden Sie zwei der schlechtesten Operatoren für jede Datenbank: berechnete Felder und Gruppierung (oder distinct) bei einem vollständigen Tabellenscan. Das Aggregationsframework muss in diesem Fall das Feld, die Gruppe und dann das In-Memory (http://docs.mongodb.org/manual/reference/aggregation/#_S_sort) berechnen, um das berechnete Feld zu sortieren. Dies ist eine äußerst ineffiziente Aufgabe für MongoDB, tatsächlich höchstwahrscheinlich irgendeine Datenbank.

Es gibt keine einfache Möglichkeit, dies in Echtzeit entsprechend Ihrer eigenen Anwendung zu tun. Map Reduce könnte ein Ausweg sein, wenn Sie die Ergebnisse nicht sofort zurückgeben müssten, aber da ich rate, dass Sie nicht wirklich auf diese Art von Zeug warten wollen, ist die Standardmethode nur, die Gruppe komplett auszurotten.

Sie können dies durch Voraggregation tun. So können Sie eine andere Sammlung von grouped_wikipedia erstellen und in Ihrer Anwendung verwalten Sie dies mit einem upsert() mit atomaren Operatoren wie $set und $inc (um die Vorkommen zu zählen), um sicherzustellen, dass Sie nur eine Zeile pro item erhalten. Dies ist wahrscheinlich die vernünftigste Methode, um dieses Problem zu lösen.

Dies wirft jedoch ein weiteres Problem der Verwaltung dieser zusätzlichen Sammlung neben der Detailkollektion wikipedia auf, aber ich glaube, dass dies ein unvermeidlicher Nebeneffekt davon ist, hier die richtige Leistung zu erzielen. Die Vorteile sind größer als der Verlust der zusätzlichen Sammlung.

+0

Aber wenn Sie eine Sammlung mit 8 Millionen Einträgen haben und Sie ständig laufen, um Ihren "Cache" auf dem neuesten Stand zu halten, verlangsamen Sie Ihre Datenbank nicht? –

+0

@RobertReiz Es könnte möglicherweise, es hängt von einigen Faktoren ab. Ich meine, Sie haben das Gewicht einer JS-Engine, aber die JS-Enigne ist nicht mehr single-threaded und es kann Sperren auf der db während seiner Verarbeitung freigeben, so ist das Problem der IO benötigt, um in die DB einmal die MR zu schreiben Wenn Sie jedoch eine MR ausführen, die nur sagen, 10.000 Zeilen pro 5 Minuten, werden Sie feststellen, dass MongoDB kann ziemlich glücklich mit der – Sammaye

+0

Ich kümmere mich nicht so sehr um den Client, aber der Mongodb-Prozess. Angenommen, ich habe 8 Millionen Einträge und für jeden Eintrag benötigt MongoDB MR 5 Minuten, dann brauche ich 27 Tage, um alle meine Caches zu berechnen. Das ist weit weg von der Echtzeit :-) –