2017-09-20 2 views
0

Ich habe eine Sammlung von Protokollen mit Millionen von Datensätzen. Das Erstellen eines neuen Indexes dauert "für immer". Daher wäre es vorzuziehen, vorhandene Indizes zu verwenden.MongoDB verwendet nicht meinen Index

Jetzt möchte ich die Anzahl der Vorkommen bestimmter Fehlercodes erhalten. Ich benutze diese Abfrage, und es funktioniert funktionell in Ordnung:

db.getCollection('logs.res').aggregate([ 
    { 
     $match:{  
      timeStamp: { 
       $gte: new Date('2017-05-01').getTime(), // timeStamp is Number 
       $lt : new Date('2017-05-02').getTime() // of ms since epoch 
      }, 
      '[email protected]': { 
       $ne: null 
      } 
     } 
    }, 
    { 
     $group: { 
      _id: '[email protected]', 
      count: {$sum: 1} 
     } 
    }, 
    { 
     $sort: { count: -1} 
    } 
]); 

Das Problem ist, dass es auch in der Nähe von 10 Sekunden dauert nur diese für einen Tag auszuführen. Ich hatte die folgende Index verwendet würde angenommen: [email protected]_1:

{ 
    "timeStamp" : -1, 
    "[email protected]" : 1 
} 

jedoch MongoDB scheint unerbittlich etwas timeStamp: 1 Index zu verwenden (mit einigen anderen Indizes in keinem Zusammenhang mit der Abfrage) und scannen alllllll die Ergebnisse, wenn einige Antworten zu sehen könnte eine ErrorCode angehängt haben, obwohl diese Information im Index enthalten sein sollte. Hier

ist die explain():

enter image description here

  • Gibt es eine Möglichkeit, die[email protected]_1Index verwenden dies zu beschleunigen?
  • Warum ist nicht es mit diesem Index? Ich bin wahrscheinlich missverstanden, wie Indizes in dieser Abfrage verwendet werden.

Lauf MongoDB 3.2.7 auf OSX.

hinweis: Ich habe auch versucht $empty: true statt $ne: null. Es führt zu den gleichen Ergebnissen, aber einige sagen, Sie können $empty nicht verwenden, wenn Sie einen zusammengesetzten Index verwenden möchten. Viele Fragen zu Stack Overflow sind jedoch alt (mongo 2.x).

Antwort

2

Gewinnplan ist CACHED PLAN. Sie können versuchen, den Cache-Plan zu löschen.

db.getCollection('logs.res').getPlanCache().clear() 

Wenn, nachdem Sie den Cache reinigen, Mongo noch den falschen Index verwendet. Sie können versuchen, den Abfrageplan zu setzen oder einen "Hinweis" zu verwenden, um Ihren Index zu erzwingen

+0

Soweit ich weiß, ist Hinting für Testzwecke und Sie können keinen Index Hinweis auf eine Aggregation Pipeline setzen. – Redsandro

+0

Sie können die Funktion PlanCacheSetFilter vor dem Aggregat – Marco

1

Reguläre Mongodb-Indizes verwenden Feldwert und Typ, um den Baum zu erstellen.

Abfragen wie $empty: true oder $ne: null haben keinen Parameter irgendeiner Art und können nicht von solchen Indizes profitieren. Es ist ein spezieller Fall und erfordert eine spezielle sparse index.

Wenn Ihr [email protected]_1 Index erstellt:

db.getCollection('logs.res').createIndex(
    { 
     "timeStamp" : -1, 
     "[email protected]" : 1 
    }, 
    { sparse: true } 
) 

sollten Sie Ihre Anfrage am besten unterstützen. Ansonsten gibt es keinen großen Unterschied zwischen [email protected]_1 und timeStamp_1_module_1_etc, da nur das erste Feld verwendet wird.

+0

verwenden. Dies könnte relevant sein. Also könnte ich '$ nin: [Array-Liste aller Fehler-IDs]' stattdessen? Oder ist ein nicht-spärlicher Index für ein Feld, das nicht immer ziemlich nutzlos ist? – Redsandro

+0

Oder noch besser: '$ ne: 999999'. Dies ist ein Parameter der Typnummer. Es wird einfach nicht benutzt. – Redsandro

+0

Ja, beide sollten den Index verwenden, aber es ist nicht die gleiche Abfrage wie '$ ne: null'. In beiden Fällen erhalten Sie Nullen. Wenn Sie alle Fehlercodes kennen, können Sie '$ in: [the list]' ausführen, aber möglicherweise verpassen Sie Dokumente mit unerwarteten Fehlercodes. –

Verwandte Themen