2016-08-07 14 views
0

Ich habe ein System, das Einträge nach Aktion aufzeichnet. Es gibt mehr als 120 Millionen von ihnen und ich möchte sie mit Aggregat von id_entry gruppieren. Die Struktur ist wie die folgende:MongoDB Aggregat von 120M Dokumenten

entry 
{ 
    id_entry: ObjectId(...), 
    created_at: Date(...), 
    action: {object}, 
} 

Wenn ich versuche, ein Aggregat von id_entry und Gruppierungs seine Aktionen zu tun, dauert es mehr als 3 Stunden zu beenden:

db.entry.aggregate([ 
{ '$match': {'created_at': { $gte:ISODate("2016-02-02"), $lt:ISODate("2016-02-03")}}}, 
{ '$group': { 
    '_id' :{'id_entry': '$id_entry'}, 
    actions: { 
     $push: '$action' 
    } 
}}]) 

Aber in diesem Bereich von Tagen gibt es nur um ~ 4M Dokumente. (id_entry und created_at hat Indizes)

Was mache ich falsch im Aggregat? Wie kann ich 3-4M Dokumente gruppieren, um sie in weniger als 3h durch id_entry zu verbinden? Dank

+1

Haben Sie einen Index für 'created_at'? Wie lange dauert diese Abfrage: 'db.entry.find ({'created_at': {$ gte: ISODate (" 2016-02-02 "), $ lt: ISODate (" 2016-02-03 ")}})' ? – DmitryZyr

+0

Hallo @ DmitryZyr, danke für die Antwort. Diese Abfrage dauerte 0.057s und ruft 2.703.103 Dokumente ab. Ich denke, das große Problem ist die Gruppierung von 2,7M-Dokumenten ... – Amarant

Antwort

0

Um Ihre bestimmte Abfrage zu beschleunigen, benötigen Sie einen Index für das Feld created_at.

Die Gesamtleistung der Aggregation hängt jedoch unter anderem auch von Ihrer Hardwarespezifikation ab.

Wenn Sie den Abfrageleistung zu finden sein weniger als das, was Sie benötigen, können Sie entweder:

  • erstellen pre-aggregated report (im Wesentlichen ein Dokument, das die aggregierten Daten enthält, die Sie benötigen, aktualisiert jedes Mal, wenn eine neue Daten eingefügt) oder
  • Verwenden Sie sharding, um Ihre Daten auf mehrere Server zu verteilen.

Wenn Sie diese Aggregation Abfrage die ganze Zeit laufen müssen, ein voraggregierten Bericht ermöglicht es Ihnen, eine extrem up-to-date aggregierten Bericht Ihrer Daten zu haben, die zugänglich ist, eine einfache find() Abfrage verwenden.

Der Kompromiss besteht darin, dass Sie für jedes Einfügen das voraggregierte Dokument aktualisieren müssen, um den aktuellen Status Ihrer Daten widerzuspiegeln. Dies ist jedoch ein relativ kleiner Kompromiss im Vergleich zu einer langen/komplexen Aggregationsabfrage, die den täglichen Betrieb beeinträchtigen könnte.

Eine Einschränkung mit dem Aggregationsrahmenwerk ist: Sobald die Aggregationspipeline eine $group oder Bühne auftritt, kann kein Index verwendet werden. Dies liegt daran, dass der MongoDB-Index an die physische Speicherung der Dokumente gebunden ist. Gruppieren und Projizieren transformieren die Dokumente in einen Zustand, in dem das Dokument keine physische Darstellung mehr auf der Festplatte hat.

Verwandte Themen