Wie wirkt sich die MongoDB-Projektion auf die Leistung aus?


10

Aus der MongoDBDokumentation geht hervor, dass:

Wenn Sie nur eine Teilmenge von Feldern aus Dokumenten benötigen, können Sie eine bessere Leistung erzielen, indem Sie nur die Felder zurückgeben, die Sie benötigen

Wie wirken sich Filterfelder auf die Leistung aus? Hängt die Leistung mit der Größe der Daten zusammen, die über das Netzwerk übertragen werden? oder die Größe der Daten, die im Speicher gespeichert werden? Wie genau wird diese Leistung verbessert? Was ist diese Leistung, die in der Dokumentation erwähnt wurde?

Ich habe langsame MongoDB-Abfragen. Beeinflusst die Rückgabe einer Teilmenge meine langsame Abfrage (ich habe einen zusammengesetzten Index für das Feld)?


Ohne den Code ist es nicht möglich, Sie vorzuschlagen. Was wird die Leistung in der Projektionsabfrage "MongoDB" tatsächlich beeinflussen? Es ist immer besser, zumindest erwähnen Sie den Code.
Md Haidar Ali Khan

@MdHaidarAliKhan Es geht nicht um den Code und meine Nutzlast. Ich möchte nur wissen, warum laut mongoDB das Filtern die Leistung beeinflusst. Aus welcher Sicht wurde diese Leistung gemessen? Zum Beispiel hilft es bei der Speichernutzung von Mongo, weil weniger Daten oder weniger Festplatten-E / A (zum Beispiel) usw. vorhanden sind.
ALH

Ich möchte nur wissen, warum laut mongoDB das Filtern die Leistung beeinflusst. Verwenden Sie Projektionen, um nur die erforderlichen Daten zurückzugeben. Ich möchte damit sagen, dass Sie eine bessere Leistung erzielen können, indem Sie nur die Felder zurückgeben, die Sie benötigen. Zum Beispiel db.posts.find ({}, {}). Sort ({}).
Md Haidar Ali Khan

Hilft es beispielsweise bei der Speichernutzung von Mongo aufgrund von weniger Daten oder weniger Festplatten-E / A (zum Beispiel) usw. Könnten Sie die MongoDB-Version und das Betriebssystem in Ihrer Umgebung aktualisieren?
Md Haidar Ali Khan

@ MdHaidarAliKhan OS ist Debian 8,MongoDB 3.6.2
ALH

Antworten:


15

Standardmäßig geben Abfragen alle Felder in übereinstimmenden Dokumenten zurück. Wenn Sie alle Felder benötigen, ist die Rückgabe vollständiger Dokumente effizienter, als wenn der Server die Ergebnismenge mit Projektionskriterien bearbeitet.

Die Verwendung der Projektion zur Begrenzung der Felder, die aus Abfrageergebnissen zurückgegeben werden sollen, kann jedoch die Leistung verbessern, indem:

  • Entfernen nicht benötigter Felder aus den Abfrageergebnissen (Einsparung von Netzwerkbandbreite)
  • Einschränken der Ergebnisfelder, um eine abgedeckte Abfrage zu erzielen (Rückgabe indizierter Abfrageergebnisse ohne Abrufen vollständiger Dokumente)

Wenn Sie mithilfe der Projektion nicht verwendete Felder entfernen, muss der MongoDB-Server jedes vollständige Dokument in den Speicher abrufen (sofern es noch nicht vorhanden ist) und die zurückzugebenden Ergebnisse filtern. Diese Verwendung der Projektion verringert nicht die Speichernutzung oder den Arbeitssatz auf dem MongoDB-Server, kann jedoch abhängig von Ihrem Datenmodell und den projizierten Feldern erhebliche Netzwerkbandbreite für Abfrageergebnisse einsparen.

Eine abgedeckte Abfrage ist ein Sonderfall, bei dem alle angeforderten Felder in einem Abfrageergebnis im verwendeten Index enthalten sind, sodass der Server nicht das vollständige Dokument abrufen muss. Abgedeckte Abfragen können die Leistung (durch Vermeiden des Abrufs von Dokumenten) und die Speichernutzung verbessern (wenn für andere Abfragen nicht dasselbe Dokument abgerufen werden muss).

Beispiele

mongoStellen Sie sich zu Demonstrationszwecken über die Shell vor, Sie hätten ein Dokument, das so aussieht:

db.data.insert({
    a: 'webscale',
    b: new Array(10*1024*1024).join('z')
})

Das Feld bkann eine Auswahl von Werten darstellen (oder in diesem Fall eine sehr lange Zeichenfolge).

Erstellen Sie als Nächstes einen Index für {a:1}ein häufig verwendetes Feld, das von Ihrem Anwendungsfall abgefragt wird:

db.data.createIndex({a:1})

Ein einfaches findOne()ohne Projektionskriterium gibt ein Abfrageergebnis zurück, das ungefähr 10 MB beträgt:

> bsonsize(db.data.findOne({}))
10485805

Durch Hinzufügen der Projektion {a:1}wird die Ausgabe auf das Feld aund das Dokument beschränkt _id(das standardmäßig enthalten ist). Der MongoDB-Server bearbeitet noch ein 10-MB-Dokument, um zwei Felder auszuwählen, aber das Abfrageergebnis beträgt jetzt nur noch 33 Byte:

> bsonsize(db.data.findOne({}, {a:1}))
33

Diese Abfrage wird nicht behandelt, da das vollständige Dokument abgerufen werden muss, um den _idWert zu ermitteln. Das _idFeld ist standardmäßig in den Abfrageergebnissen enthalten, da es die eindeutige Kennung für ein Dokument ist, jedoch _idnicht in einen Sekundärindex aufgenommen wird, sofern es nicht ausdrücklich hinzugefügt wird.

Die totalDocsExaminedund totalKeysExaminedMetriken in den explain()Ergebnissen zeigen, wie viele Dokumente und Indexschlüssel untersucht wurden:

 > db.data.find(
     {a:'webscale'}, 
     {a:1}
 ).explain('executionStats').executionStats.totalDocsExamined
 > 1

Diese Abfrage kann mithilfe der Projektion verbessert werden, um das _idFeld auszuschließen und eine abgedeckte Abfrage nur mit dem {a:1}Index zu erstellen . Die abgedeckte Abfrage muss kein ~ 10 MB großes Dokument mehr in den Speicher abrufen und ist daher sowohl bei der Netzwerk- als auch bei der Speichernutzung effizient:

 > db.data.find(
     {a:'webscale'},
     {a:1, _id:0}
 ).explain('executionStats').executionStats.totalDocsExamined
 0

 > bsonsize(db.data.findOne( {a:'webscale'},{a:1, _id:0}))
 21

Ich habe langsame MongoDB-Abfragen. Beeinflusst die Rückgabe einer Teilmenge meine langsame Abfrage (ich habe einen zusammengesetzten Index für das Feld)?

Dies ist ohne den Kontext einer bestimmten Abfrage, eines Beispieldokuments und der vollständigen EXPLAIN-Ausgabe nicht zu beantworten. Sie können jedoch einige Benchmarks in Ihrer eigenen Umgebung für dieselbe Abfrage mit und ohne Projektion ausführen, um das Ergebnis zu vergleichen. Wenn Ihre Projektion die Gesamtausführungszeit für Abfragen (Verarbeitung und Übertragung von Ergebnissen) erheblich verkürzt, kann dies ein starker Hinweis darauf sein, dass Ihr Datenmodell verbessert werden könnte.

Wenn nicht klar ist, warum eine Abfrage langsam ist, ist es am besten, eine neue Frage mit bestimmten Details zu veröffentlichen, um sie zu untersuchen.


1
Ich schätze die gründliche Erklärung des Problems sehr. Es scheint, dass es nicht möglich ist, Abfragen abzudecken, da meine Antwort viel mehr Daten enthält als innerhalb des Index. Meine Hauptfrage ist hier, ich würde mich freuen, wenn Sie einen Blick darauf werfen
ALH

1

Mit einer Projektion können Sie eine Situation erreichen, in der die Ergebnismenge direkt aus dem Index stammt.

Wenn Sie einen zusammengesetzten Index haben, {x:1, y:1, z:1}bei dem keines von x, y, z _id ist, müssen Sie projizieren, {_id:0, x:1, y:1, z:1}da er _idimmer als Teil der Ergebnismenge zurückgegeben wird (wenn er nicht wegprojiziert wird) und die Engine Datendateien lesen muss, um ihn abzurufen. Dies liegt daran, dass der Index nicht den Wert _id hat, sondern nur auf das Dokument verweist, in dem der Wert gespeichert ist.


Wenn ich also _idaus der zurückgegebenen Antwort entferne , passt das in den Arbeitsspeicher? Hilft das?
ALH

1
MongoD (versucht), mindestens Indizes im Speicher zu halten (und so viele Daten, wie passen). Wenn Ihre Abfrage direkt aus dem Index ausgefüllt werden kann und Sie projizieren, _id:0wird das Ergebnis vollständig aus dem RAM zurückgegeben, ohne Daten von der Festplatte zu lesen.
JJussi
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.