Tipps zur Optimierung von Aggregation-Pipelines
Sie strukturieren Aggregation-Pipelines so um, dass $match und $project früh ausgeführt werden, vermeiden $unwind vor $match und verwenden allowDiskUse für große Sortiervorgänge.
Tipps zur Optimierung von Aggregation-Pipelines ist eine kostenlose MongoDB Academy-Lektion auf CoddyKit. Dies ist Lektion 4 von 4. Du kannst die komplette Lektion unten kostenlos lesen – dann übst du sie direkt im Browser mit einem integrierten Code-Editor und einem KI-Tutor rund um die Uhr. Sie ist Teil des MongoDB Academy-Lernpfads, und dein Fortschritt wird über Web und CoddyKit-App synchronisiert. Der MongoDB Academy-Kurs umfasst insgesamt 4 Lektionen.
Aggregationsleistung: Der große Überblick
Aggregationspipelines können teuer sein – sie können Millionen von Dokumenten durchsuchen, große Strukturen im Arbeitsspeicher aufbauen und für mehrere Sekunden blockieren. Der Schlüssel zu schnellen Pipelines besteht darin, datenreduzierende Stufen so früh wie möglich anzuwenden, damit spätere Stufen mit einem möglichst kleinen Datensatz arbeiten. MongoDB verfügt außerdem über einen internen Optimierer, der bestimmte Stufen automatisch neu anordnet. Wenn Sie manuelle Optimierungen verstehen, haben Sie jedoch die größte Kontrolle.
$match früh einsetzen: Vor der Transformation filtern
$match ist die Filterstufe von MongoDB. Wenn Sie sie so früh wie möglich in der Pipeline platzieren, verringern Sie die Anzahl der Dokumente, die in jede nachfolgende Stufe gelangen. Kann $match einen Index verwenden, wird es zu einem äußerst schnellen ersten Schritt. Selbst ein frühes $match ohne Index ist besser als ein spätes – so vermeiden Sie die Verarbeitung von Dokumenten, die ohnehin verworfen werden.
// BAD: $group processes all 1M docs, then $match discards most
db.orders.aggregate([
{ $group: { _id: '$status', total: { $sum: '$amount' } } },
{ $match: { _id: 'pending' } } // late match
])
// GOOD: $match first — only 'pending' docs enter $group
db.orders.aggregate([
{ $match: { status: 'pending' } }, // early match, uses index
{ $group: { _id: '$customerId', total: { $sum: '$amount' } } }
])$project früh einsetzen: Dokumentgröße reduzieren
Verwenden Sie $project früh, um Felder zu entfernen, die Sie in späteren Stufen nicht benötigen. Weniger Felder pro Dokument bedeuten kleinere Darstellungen im Arbeitsspeicher, die durch die Pipeline fließen, und reduzieren dadurch den Speicherbedarf und die CPU-Zeit. Entfernen Sie nur Felder, bei denen Sie sicher sind, dass sie nicht benötigt werden – ein zu aggressives frühes $project, das ein in einer späteren Stufe verwendetes Feld entfernt, führt zu einem Fehler.
// Drop large, unused fields early
db.products.aggregate([
{ $match: { category: 'electronics' } },
// Remove bulky description and image fields early
{ $project: { name: 1, price: 1, stock: 1 } },
{ $group: { _id: null, avgPrice: { $avg: '$price' } } }
])Pipeline-Optimierer: Automatische Neuschreibungen
Der Aggregationsoptimierer von MongoDB wendet vor der Ausführung Ihrer Pipeline automatisch mehrere Neuschreibungen an. Wichtige automatische Neuschreibungen: 1) Führt aufeinanderfolgende $match-Stufen zu einer einzigen zusammen. 2) Verschiebt $match nach Möglichkeit vor $skip und $limit. 3) Führt aufeinanderfolgende $limit-Stufen zusammen. 4) Verschiebt $match vor $lookup, um vor dem Join zu filtern. Verwenden Sie explain(), um die optimierte Pipeline anzuzeigen.
// View the optimizer's rewritten pipeline
db.orders.explain().aggregate([
{ $lookup: { from: 'customers', localField: 'customerId',
foreignField: '_id', as: 'customer' } },
{ $match: { 'customer.country': 'US' } }
])
// Optimizer may push $match before $lookup if fields allow$unwind nicht vor $match einsetzen
$unwind zerlegt ein Array in mehrere Dokumente – eines pro Array-Element. Wenn Sie $match nach $unwind platzieren, tragen Sie zunächst die vollständigen Kosten der Erweiterung, bevor gefiltert wird. Filtern Sie nach Möglichkeit vor $unwind, um die Anzahl der Array-Elemente zu reduzieren, die erweitert werden müssen. Bei großen Arrays kann dies die Dokumentanzahl um eine Größenordnung verringern.
// BAD: unwind first creates N*arraySize docs, then filter
db.blogs.aggregate([
{ $unwind: '$tags' },
{ $match: { tags: 'mongodb' } }
])
// GOOD: filter the root document first, then unwind
db.blogs.aggregate([
{ $match: { tags: 'mongodb' } }, // uses index on tags array
{ $unwind: '$tags' },
{ $match: { tags: 'mongodb' } } // refine after unwind
])Indexabdeckung für $match und $sort
Die erste $match-Stufe einer Pipeline kann genau wie eine find()-Abfrage einen Index der Collection verwenden. Auch die erste $sort-Stufe kann einen Index verwenden, um eine Sortierung im Arbeitsspeicher zu vermeiden – allerdings nur, wenn sie vor jeder Stufe steht, die die Dokumentstruktur verändert, etwa $project oder $group. Strukturieren Sie Ihre Pipelines so, dass frühe $match- und $sort-Stufen von Indexen profitieren.
// Index supports $match and $sort at the start
db.events.createIndex({ userId: 1, createdAt: -1 })
db.events.aggregate([
{ $match: { userId: 'u123' } }, // uses index
{ $sort: { createdAt: -1 } }, // uses index sort order
{ $limit: 20 },
{ $project: { _id: 0, type: 1, payload: 1 } }
])allowDiskUse für große Sortierungen
Standardmäßig ist jede Aggregationsstufe auf 100 MB Arbeitsspeicher begrenzt. Überschreitet eine $sort-, $group- oder $bucket-Stufe dieses Limit, schlägt die Pipeline mit einem Fehler fehl. Wenn Sie allowDiskUse: true setzen, kann die Pipeline Daten auf die Festplatte auslagern und dadurch beliebig große Sortierungen ermöglichen – allerdings auf Kosten langsamerer E/A-Vorgänge. Die richtige Lösung besteht meist darin, einen Index hinzuzufügen oder vor der Sortierung aggressiver zu filtern.
// Allow spill to disk for large aggregations
db.events.aggregate(
[
{ $match: { year: 2024 } },
{ $sort: { amount: -1 } },
{ $group: { _id: '$region', total: { $sum: '$amount' } } }
],
{ allowDiskUse: true }
)$lookup-Leistung: Vor dem Join filtern
$lookup entspricht in der Aggregation einem SQL-JOIN und ist eine der teuersten Stufen. So minimieren Sie die Kosten: 1) Platzieren Sie $match vor $lookup, damit weniger Dokumente verknüpft werden müssen. 2) Stellen Sie sicher, dass die verknüpfte Collection einen Index für foreignField besitzt. 3) Verwenden Sie die Pipeline-Form von $lookup mit einem darin enthaltenen $match, um die verknüpften Ergebnisse sofort zu filtern.
// Ensure foreignField is indexed
db.customers.createIndex({ _id: 1 }) // usually already indexed
// Use pipeline $lookup with internal $match to reduce joined docs
db.orders.aggregate([
{ $match: { status: 'pending' } },
{ $lookup: {
from: 'customers',
let: { cid: '$customerId' },
pipeline: [
{ $match: { $expr: { $eq: ['$_id', '$$cid'] } } },
{ $project: { name: 1, email: 1 } } // trim early
],
as: 'customer'
}}
])$limit in Paginierungs-Pipelines früh einsetzen
Wenn Sie Endpunkte für paginierte Listen erstellen, verschieben Sie $limit nach dem Filtern und Sortieren so früh wie möglich nach vorne. Eine Pipeline, die 100.000 Dokumente durch $lookup und $addFields verarbeitet, bevor sie auf 20 begrenzt wird, ist 5.000-mal teurer als eine Pipeline, die zuerst begrenzt. Bei der Keyset-Paginierung macht ein Bereichsfilter $skip häufig vollständig überflüssig.
// Efficient pagination: limit BEFORE expensive stages
db.products.aggregate([
{ $match: { category: 'books' } },
{ $sort: { rating: -1 } },
{ $limit: 20 }, // limit early!
{ $lookup: { from: 'reviews',
localField: '_id', foreignField: 'productId', as: 'reviews' } }
])Mit materialisierten Sichten vorberechnen
Für teure Aggregationen, die Dashboards oder Berichte versorgen, sollten Sie materialisierte Sichten mit $merge oder $out in Betracht ziehen. Führen Sie die aufwendige Aggregation nach einem Zeitplan aus, beispielsweise jede Stunde, und schreiben Sie die Ergebnisse in eine eigene Collection. Abfragen der materialisierten Sicht sind kostengünstige Punktabfragen statt teurer Pipeline-Scans. Atlas unterstützt über Trigger auch On-Demand Materialised Views.
// Materialise daily revenue summary
db.orders.aggregate([
{ $match: { createdAt: { $gte: ISODate('2025-01-01') } } },
{ $group: { _id: '$region', revenue: { $sum: '$amount' } } },
{ $merge: {
into: 'revenue_summary',
whenMatched: 'replace',
whenNotMatched: 'insert'
}}
])Aggregationspipelines profilieren
Verwenden Sie bei einer Aggregation .explain('executionStats'), um zu sehen, wie viele Dokumente jede Stufe ausgegeben hat. Achten Sie auf Stufen, bei denen nReturned stark abnimmt – dort findet die eigentliche Arbeit statt. Wenn eine Stufe weiterhin Millionen von Dokumenten verarbeitet, fügen Sie davor ein $match hinzu oder verbessern Sie den Index. Für Atlas zeigt der Query Profiler außerdem die Leistung von Aggregationspipelines im Zeitverlauf.
db.orders.explain('executionStats').aggregate([
{ $match: { status: 'shipped' } },
{ $group: { _id: '$region', total: { $sum: '$amount' } } },
{ $sort: { total: -1 } },
{ $limit: 10 }
])
// Check: nReturned per stage, executionTimeMillisEstimateKurzer Test
Testen Sie Ihr Verständnis der Konzepte zu MongoDB & NoSQL-Datenbanken aus dieser Lektion.
Zusammenfassung der Lektion
In dieser Lektion haben Sie gelernt: $match und $project so früh wie möglich einzusetzen, um das Dokumentvolumen in späteren Stufen zu minimieren, sicherzustellen, dass das erste $match und $sort Indexe verwenden, um Collection-Scans und Sortierungen im Arbeitsspeicher zu vermeiden und allowDiskUse für unvermeidbar große Sortierungen zu verwenden, aber bessere Indexe oder frühere Filter als dauerhafte Lösung zu bevorzugen. Als Nächstes sehen wir uns Atlas Data Federation an.
Lerne JavaScript mit einem KI-Tutor — kostenlos
Schreibe und führe echten Code in deinem Browser aus, bekomme sofortige Hilfe von einem 24/7 KI-Tutor und setze dein Lernen im Web oder in der App fort.
- Kurse
- 30
- Lektionen
- 120
Häufig gestellte Fragen
Ist die Lektion „Tipps zur Optimierung von Aggregation-Pipelines“ kostenlos?
Ja — der vollständige Text von „Tipps zur Optimierung von Aggregation-Pipelines“ ist hier im Web kostenlos zu lesen. Um sie interaktiv zu üben (integrierter Code-Editor und 24/7 KI-Tutor) und den Rest des MongoDB Academy-Kurses freizuschalten, upgrade auf CoddyKit PRO. Der MongoDB Academy-Kurs umfasst insgesamt 4 Lektionen.
Was lerne ich in „Tipps zur Optimierung von Aggregation-Pipelines“?
Sie strukturieren Aggregation-Pipelines so um, dass $match und $project früh ausgeführt werden, vermeiden $unwind vor $match und verwenden allowDiskUse für große Sortiervorgänge. Du übst MongoDB Academy mit praktischem Code, den du direkt im Browser ausführst, und ein 24/7 KI-Tutor beantwortet deine Fragen während du die Lektion bearbeitest.
Brauche ich Erfahrung, um MongoDB Academy zu starten?
Keine Vorkenntnisse erforderlich. MongoDB Academy auf CoddyKit ist für Anfänger bis fortgeschrittene Lernende strukturiert, sodass du hier starten oder von Anfang an beginnen und in deinem eigenen Tempo voranschreiten kannst. Dies ist Lektion 4 von 4.
Wie lange dauert die Lektion „Tipps zur Optimierung von Aggregation-Pipelines“?
Die meisten CoddyKit-Lektionen dauern etwa 5–10 Minuten. Jede ist kompakt und interaktiv, sodass du stetig Fortschritte machst und genau dort weitermachst, wo du aufgehört hast – im Web und in der App.
Kann ich in dieser MongoDB Academy-Lektion Code schreiben und ausführen?
Ja. Jede MongoDB Academy-Lektion enthält einen integrierten Code-Editor, sodass du echten Code direkt in deinem Browser schreibst und ausführst und sofort KI-Feedback erhältst — ohne lokale Einrichtung erforderlich.
Alle Lektionen in diesem Kurs
- Der Database Profiler und das Slow-Query-Log
- Präfixregel für zusammengesetzte Indizes und ESR-Prinzip
- Index-Intersection und zusammengesetzte Indizes
- Tipps zur Optimierung von Aggregation-Pipelines