2016-03-24 10 views
1

finden habe ich eine mondoDB Sammlung wie folgt, die fast eine Million Einträge enthält:MongoDB langsam auf Sub-Array-Abfrage

{ 
_id: 'object id', 
link: 'a url', 
channels: [ array of ids ] 
pubDate: Date 
} 

Ich habe die folgende Abfrage, die ich ziemlich oft durchführen:

db.articles.find({ $and: [ { pubDate: { $gte: new Date(<some date>) } }, { channels: ObjectId(<some object id>) } ] }) 

Die Abfrage ist extrem langsam, obwohl ich bestimmte Indizes an Ort und Stelle habe. Vor kurzem lief ich auf sich eine erklären und hier ist das Ergebnis:

{ 
    "cursor" : "BtreeCursor pubDate_-1_channels_1", 
    "isMultiKey" : true, 
    "n" : 2926, 
    "nscannedObjects" : 4245, 
    "nscanned" : 52611, 
    "nscannedObjectsAllPlans" : 8125, 
    "nscannedAllPlans" : 56491, 
    "scanAndOrder" : false, 
    "indexOnly" : false, 
    "nYields" : 5, 
    "nChunkSkips" : 0, 
    "millis" : 5378, 
    "indexBounds" : { 
     "pubDate" : [ 
      [ 
       ISODate("0NaN-NaN-NaNTNaN:NaN:NaNZ"), 
       ISODate("2016-03-04T21:00:00Z") 
      ] 
     ], 
     "channels" : [ 
      [ 
       ObjectId("54239b9477456cf777dd0d31"), 
       ObjectId("54239b9477456cf777dd0d31") 
      ] 
     ] 
    } 
} 

Sieht aus wie es den richtigen Index verwendet, aber immer noch mehr als 5 Sekunden dauern zu laufen.

Fehle ich hier etwas? Stimmt etwas nicht mit meinem Index?

Hier sind die Indizes für die Sammlung btw:

[ 
    { 
     "v" : 1, 
     "name" : "_id_", 
     "key" : { 
      "_id" : 1 
     }, 
     "ns" : "dbname.articles" 
    }, 
    { 
     "v" : 1, 
     "name" : "pubDate_-1_channels_1", 
     "key" : { 
      "pubDate" : -1, 
      "channels" : 1 
     }, 
     "ns" : "dbname.articles", 
     "background" : true 
    }, 
    { 
     "v" : 1, 
     "name" : "pubDate_-1", 
     "key" : { 
      "pubDate" : -1 
     }, 
     "ns" : "dbname.articles", 
     "background" : true 
    }, 
    { 
     "v" : 1, 
     "name" : "link_1", 
     "key" : { 
      "link" : 1 
     }, 
     "ns" : "dbname.articles", 
     "background" : true 
    } 
] 

Hier ist, was ich sehe, wenn ich Statistiken über die Sammlung laufen:

{ 
    "ns" : "dbname.articles", 
    "count" : 2402741, 
    "size" : 2838416144, 
    "avgObjSize" : 1181.3242226274076, 
    "storageSize" : 3311443968, 
    "numExtents" : 21, 
    "nindexes" : 4, 
    "lastExtentSize" : 862072832, 
    "paddingFactor" : 1.000000000020535, 
    "systemFlags" : 0, 
    "userFlags" : 0, 
    "totalIndexSize" : 775150208, 
    "indexSizes" : { 
     "_id_" : 100834608, 
     "pubDate_-1_channels_1" : 180812240, 
     "pubDate_-1" : 96378688, 
     "link_1" : 397124672 
    }, 
    "ok" : 1 
} 
+0

Ihre Indexierungsstrategie sieht gut aus. Beachten Sie, dass MongoDB langsam wird, wenn all Ihre Dokumente nicht mehr in den Arbeitsspeicher passen, und sehr langsam, wenn alle indizierten Felder nicht in den Arbeitsspeicher passen. Könnten Sie bitte die Frage bearbeiten und das Ergebnis von [db.my_collection.stats()] (https://docs.mongodb.org/manual/reference/method/db.collection.stats/) hinzufügen und uns mitteilen, wie viele GB von RAM haben Sie auf Ihrem Computer? – CydrickT

+0

Danke @CydrickT Ich habe die Statistikdaten hinzugefügt. Die Maschine hat 1,5 GB Ram, es ist eine kleine EC2-Instanz.Ich denke, es könnte sehr wohl das Speicherproblem sein. – aqqush

+0

Ich habe eine vollständige Antwort @aqqush hinzugefügt. Wenn es Verwirrung gibt, zögern Sie nicht, einen Kommentar zu schreiben. – CydrickT

Antwort

0

So, nach db.my_collection.stats(), nimmt indizierte Felder 0,77 GB ("totalIndexSize" : 775150208 Bytes), und Ihre Sammlung dauert 3,31 GB ("storageSize" : 3311443968 Bytes). Sie haben erwähnt, dass Ihre Instanz 1,5 GB RAM verwendet.

MongoDB kann daher alle Indizes im Speicher behalten, verfügt jedoch nicht über genügend Speicher für alle Dokumente. Wenn also eine Abfrage für Dokumente ausgeführt werden muss, die nicht im Arbeitsspeicher geladen sind, ist es langsamer. Ich wette, wenn Sie die gleiche Abfrage zweimal ausführen, würde es viel weniger Zeit dauern, da die erforderlichen Dokumente bereits im Arbeitsspeicher geladen wurden.

Ich würde empfehlen, mit 5 GB RAM zu versuchen. Führen Sie einige Abfragen durch, damit alle Dokumente in den Speicher geladen werden, und vergleichen Sie dann die Geschwindigkeiten.

0

Ihr Index {pubDate: -1, Kanal : 1} sieht gut aus für mich.

Ich würde versuchen, {channel: 1, pubDate: -1} obwohl.

Der Grund für diesen Vorschlag ist die folgende:

Beachten Sie, dass Indizes Ordnung. Der von Ihnen verwendete Index ist pubDate_-1_channels_1, der sich vom Index channels_1_pubDate_-1 (in umgekehrter Reihenfolge) unterscheidet.

Abhängig von der Anzahl der Kanäle, die Sie haben, würde ich erwarten, dass ein Index effizienter als ein anderer für Ihre Abfrage sein sollte.

Weitere Informationen finden Sie im Handbuch unter prefixes.

Verwandte Themen