Kurs
Wie bei jeder Datenbank sind Indizes auch in MongoDB ein zentraler Bestandteil der Entwicklung. Ohne sie nimmt die Performance mit wachsendem Datenvolumen stetig ab. Mit passenden Indizes bleibt der Datenzugriff auch bei Wachstum performant.
In diesem Artikel schauen wir uns die verschiedenen Index-Typen in MongoDB an, geben dir Tipps aus der Praxis und zeigen, wie du sicherstellst, dass deine Abfragen die erstellten Indizes wirklich nutzen. Wenn du noch in MongoDB einsteigst, empfehlen wir dir den Kurs Introduction to MongoDB.
Wo sind MongoDB-Indizes wichtig – und warum?
Bei Indizes geht es um Performance. Sie entscheiden, ob für eine Abfrage die komplette Collection durchsucht werden muss oder nur ein eng abgegrenzter Teil, der zur Abfrage passt. Bei kleinen Collections ist das kaum spürbar. Aber wenn 100.000 Dokumente vorhanden sind und nur 100 davon zur Abfrage passen, dauert das Durchsuchen aller 100.000 ohne passenden Index deutlich länger.
In MongoDB gibt es zahlreiche Index-Typen:
- Einzelfeld: Ein Index auf genau einem Feld des Dokuments. Der Standardindex auf dem Feld
_idist ein Einzelfeldindex. - Zusammengesetzt: Ein Index über mehrere Felder eines Dokuments. Die Reihenfolge der Felder in Abfrage und Index ist dabei entscheidend.
- Multikey: Ein Index für Array-Felder.
- Wildcard: Ein Index für Felder, deren Namen zwischen Dokumenten variieren können. Er ist in der Regel weniger performant als andere Indizes.
- Geospatial: Ein Index zur Beschleunigung georäumlicher Abfragen mit Längen- und Breitengrad.
- Gehasht: Ein Index, der sich besonders für Shard-Keys eignet.
Mehr Details zu den Index-Typen findest du in der MongoDB-Dokumentation.
In der Praxis wirst du meist Einzelfeld-, zusammengesetzte oder Multikey-Indizes verwenden – was genau sinnvoll ist, hängt immer von Anwendung, Abfragen und Daten ab.
Indizes sind für alle Datenbankoperationen wichtig, die Dokumente finden müssen. Das gilt nicht nur für find oder findOne. Auch beim Aktualisieren und Löschen nutzt die Datenbank ein Match-Kriterium, um die betroffenen Dokumente zu ermitteln.
Nicht nur find und findOne profitieren von Indizes. Verwendest du $match als erste Stufe in einer Aggregation-Pipeline, beschleunigt ein Index die Ausführung erheblich.
MongoDB-Indexierung: Tipps und Tricks für den Erfolg
Zufällig Indizes anzulegen kann genauso ineffizient sein wie ganz ohne Indizes zu arbeiten. Beachte stattdessen ein paar Grundsätze, um deine Anwendung spürbar effizienter zu machen.
Equality, Sort, Range (ESR) für zusammengesetzte Indizes
Die Faustregel für zusammengesetzte Indizes: Überlege, wie die Felder in deiner Abfrage genutzt werden, und richte den Index nach dem ESR-Best-Practice aus.
Was bedeutet ESR? Kurz erklärt:
- Equality: Felder, auf die exakt gematcht wird, nicht unscharf. Beispiel: Der exakte Name einer Person in der Abfrage.
- Sort: Felder, nach denen auf- oder absteigend sortiert wird.
- Range: Felder, auf die mit Bereichsoperatoren gematcht wird, also kein exakter Wert. Beispiel:
$ltoder$gtfinden Werte innerhalb eines Bereichs.
Ein Beispiel macht es greifbarer. Betrachte diese Abfrage:
db.employee.find(
{
"department": "Developer Relations",
"salary": {
"$lt": 80000
}
}
).sort(
{
"name": 1
}
);
Hier erfolgt ein Equality-Match auf department, ein Range-Match auf salary und eine Sortierung nach name.
Nach ESR-Regel sähe der Index so aus:
db.employee.createIndex({
"department": 1,
"name": 1,
"salary": 1
});
So vermeidest du In-Memory-Sorts und reduzierst die Suchmenge für eine performante Ausführung.
Covered Queries
Indizes reduzieren allgemein die zu scannende Dokumentenmenge und verbessern so die Performance. Noch schneller wird es mit Covered Queries: Dann liefert der Index alle benötigten Ergebnisse direkt, ohne dass Dokumente in der Collection gelesen werden müssen.
Dafür gelten ein paar Bedingungen, die je nach Anwendung erfüllt sind oder nicht:
- Match-Kriterien und Sortierung müssen exakt zum Index passen.
- Auch die in der Projektion angeforderten Felder müssen im Index enthalten sein.
- Bei Sharding muss der Shard-Key Teil des Index sein.
Was heißt das konkret?
Nehmen wir folgenden Index:
db.department.createIndex({
"country": 1,
"salary": 1
});
Wir indexieren nach country und salary. Dann führen wir diese Abfrage aus:
db.department.find(
{
"country": "US"
},
{
"country": 1,
"salary": 1
}
);
Diese Abfrage mit Projektion nutzt zwar den Index, ist aber keine Covered Query. MongoDB gibt standardmäßig das Feld _id zurück, das in unserem Index fehlt. Wir können also entweder den Index anpassen oder die Abfrage ändern. Wenn wir die Abfrage ändern, sähe sie so aus:
db.department.find(
{
"country": "US"
},
{
"country": 1,
"salary": 1,
"_id": 0
}
);
Merke: Für eine Covered Query muss der Index passen und alle angeforderten Felder enthalten. Andernfalls findest du nur Dokumente mithilfe des Index – aber liest sie aus der Collection.
Ob eine Covered Query genutzt wird, kannst du mit dem Argument executionStats in explain prüfen. Entscheidend ist totalDocsExamined. Steht dort 0, handelt es sich um eine Covered Query.
Überflüssige Indizes reduzieren oder entfernen
Indizes sind nicht kostenlos – sie verbrauchen Serverressourcen. Jeder Index muss gepflegt werden und benötigt CPU, RAM und Speicherplatz. Viele Indizes erzeugen Overhead, was auf unterdimensionierten Servern zu höheren Kosten oder geringerer Performance führen kann – nicht nur beim Lesen, sondern auch bei Schreib- und Löschvorgängen, da MongoDB mehr Ressourcen benötigt.
Lege Indizes am besten nur für häufige Abfragen an. Muss die monatliche Auswertung wirklich einen eigenen Index haben? Eher nicht. Die Abfrage, die alle 10 Sekunden läuft? Auf jeden Fall!
Weitere Best Practices zur Indexierung findest du im MongoDB-Blog.
Funktioniert dein MongoDB-Index wirklich?
Nur weil ein Index existiert, heißt das nicht, dass deine Abfrage ihn auch nutzt. In MongoDB kannst du prüfen, welcher Index für eine konkrete Abfrage verwendet wird.
Beispielindex:
db.people.createIndex({
"name": 1,
"is_active": 1
});
Wir indexieren die Felder name und is_active. Nun diese Abfrage:
db.people.find({
"is_active": true
});
Die Abfrage läuft mit oder ohne Index. Auf kleinen Datensätzen ist sie ohnehin schnell. Um zu prüfen, ob der Index genutzt wird, ergänzen wir Folgendes:
db.people.find({
"is_active": true
}).explain();
Mit explain erhalten wir den Ausführungsplan. Darin könnte Folgendes stehen:
winningPlan: {
isCached: false,
stage: 'COLLSCAN',
filter: { is_active: { '$eq': true } },
direction: 'forward'
}
Hier wurde ein "COLLSCAN" durchgeführt – der Index wurde also trotz passendem Feld nicht genutzt. Ändern wir die Abfrage so:
db.people.find({
"name": "Nic Raboy",
"is_active": true
}).explain();
Jetzt ändert sich das Ergebnis von explain:
winningPlan: {
isCached: false,
stage: 'FETCH',
inputStage: {
stage: 'IXSCAN',
keyPattern: { name: 1, is_active: 1 },
indexName: 'name_1_is_active_1',
isMultiKey: false,
multiKeyPaths: { name: [], is_active: [] },
isUnique: false,
isSparse: false,
isPartial: false,
indexVersion: 2,
direction: 'forward',
indexBounds: {
name: [ '["Nic Raboy", "Nic Raboy"]' ],
is_active: [ '[true, true]' ]
}
}
},
Jetzt wird ein "IXSCAN" verwendet, inklusive Name des genutzten Index, hier name_1_is_active_1. Der Name wurde beim Erstellen automatisch vergeben.
Für update-Operationen funktioniert es ähnlich – nur sitzt die explain-Funktion an einer anderen Stelle.
Eine update-Operation könnte so aussehen:
db.people.explain().update(
{
“name”: “Nic Raboy”,
“Is_active”: true
},
{
“$set”: { “is_active”: false }
}
);
Beachte: Hier wird explain vor update aufgerufen.
Wenn dein Update den erwarteten Index nutzt, siehst du "IXSCAN" und den Indexnamen. Mehr zu Update-Operationen und Indexen.
Alternativ kannst du den Ausführungsplan auch mit runCommand auf der Datenbank abfragen. Weniger hübsch, aber sehr mächtig – zum Beispiel so:
db.runCommand({
"explain": {
"update": "people",
"updates": [
{
"q": {
"name": "Nic Raboy",
"is_active": true
},
"u": {
"$set": { "is_active": false }
}
}
]
},
"verbosity": "allPlansExecution"
});
Das entspricht funktional dem explain bei der Update-Operation.
Wenn du unsicher beim Erstellen von Indizes bist oder ungewöhnlich langsame Abfragen siehst, schau dir die Ausführungsdetails an.
Fazit
Du hast zentrale Best Practices für Indizes in MongoDB kennengelernt. Auch wenn wir nicht jeden Spezialfall abgedeckt haben, hast du jetzt eine solide Basis, um deinen Nutzerinnen und Nutzern beim Arbeiten mit deinen Daten die bestmögliche Performance zu bieten.
Zur Erinnerung die wichtigsten Punkte:
- Halte dich, wenn möglich, an die Equality–Sort–Range-(ESR)-Regel.
- Nutze Covered Queries, wenn es deine Anforderungen erlauben.
- Erstelle nicht wahllos Indizes. Identifiziere die wichtigsten Abfragen und deren Datenvolumen.
- Verlass dich beim Testen auf den Operator
explainund bewerte damit Performance und Index-Nutzung.
Diese Liste ist nicht vollständig. Weitere Faktoren können eine Rolle spielen, zum Beispiel die Kardinalität.
Mehr Unterstützung zur Indexierung findest du in der MongoDB-Dokumentation. Wenn du eine bezahlte Stufe in MongoDB Atlas nutzt, schau dir die integrierten Performance-Advisor-Tools für Index- und Abfrageempfehlungen an.
MongoDB Indexing: Häufige Fragen
Wie viele Indizes sollte ich in einer MongoDB-Collection erstellen?
Es kommt darauf an. Finde ein sinnvolles Gleichgewicht – in der Regel lohnt sich Indexierung für häufig ausgeführte Abfragen, nicht für gelegentliche.
Ich habe mehrere Indizes erstellt, aber meine Abfragen sind weiterhin langsam. Woran liegt das?
Bist du sicher, dass deine Abfragen die erstellten Indizes wirklich nutzen? Verwende den Operator explain oder die Advisor-Tools in MongoDB Atlas zur Fehlersuche.
Muss die Reihenfolge der Indexfelder bei ESR exakt Equality, dann Sort, dann Range sein?
MongoDB kann einen Index in manchen Fällen auch außerhalb der Reihenfolge nutzen. Am wirkungsvollsten ist er jedoch, wenn die Indexreihenfolge der Abfolge in der Abfrage entspricht: zuerst Equality-Filter, dann Sortierung, zuletzt Range.
Welche explain-Modi gibt es?
Standardmäßig läuft explain() im Modus „queryPlanner“. Zusätzlich gibt es die Modi „executionStats“ und „allPlansExecution“.

Nic Raboy ist Developer Relations Lead bei MongoDB. Er leitet ein Team von Python-, Java-, C#- und PHP-Entwicklern, die großartige Inhalte erstellen, um Entwicklern zu helfen, MongoDB erfolgreich in ihre Projekte einzubinden. Er hat Erfahrung mit Golang und JavaScript und schreibt oft über seine Entwicklungsabenteuer.
