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
mongo
Stellen 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 b
kann 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 a
und 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 _id
Wert zu ermitteln. Das _id
Feld ist standardmäßig in den Abfrageergebnissen enthalten, da es die eindeutige Kennung für ein Dokument ist, jedoch _id
nicht in einen Sekundärindex aufgenommen wird, sofern es nicht ausdrücklich hinzugefügt wird.
Die totalDocsExamined
und totalKeysExamined
Metriken 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 _id
Feld 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.