Bewährte Methoden zur Verwaltung und Reduzierung des MongoDB-Festplattenspeicherverbrauchs

Optimieren Sie Ihren MongoDB-Festplattenverbrauch mit diesem umfassenden Leitfaden zu bewährten Methoden. Lernen Sie effektive Strategien zum Komprimieren von Sammlungen und Indizes, zum Identifizieren und Entfernen unnötiger Indizes sowie zur Nutzung der Komprimierungsfunktionen von WiredTiger. Entdecken Sie, wie Sie Datenarchivierung implementieren, die Oplog-Größe verwalten und den Festplattenspeicher proaktiv überwachen, um Systemausfälle zu verhindern und die Leistung zu verbessern. Dieser Artikel bietet umsetzbare Einblicke und praktische Beispiele, um Ihre MongoDB-Bereitstellungen schlank und effizient zu halten.

Bewährte Methoden zur Verwaltung und Reduzierung des MongoDB-Festplattenspeicherverbrauchs

Der MongoDB-Festplattenverbrauch wird meist dann dringend, wenn es am ungünstigsten ist: Ein Batch-Job läuft länger als erwartet, Löschungen scheinen keinen Speicherplatz freizugeben, oder ein Replica-Set-Mitglied warnt, dass das Volume fast voll ist. Die Lösung ist selten ein einzelner magischer Befehl. Sie müssen wissen, ob es sich um Live-Daten, Indizes, wiederverwendbaren WiredTiger-Speicherplatz, Oplog, Logs oder lokale Backups handelt.

Der sicherste Ansatz ist, zuerst zu messen, dann zu reduzieren, was nicht mehr existieren muss, und erst dann schwerere Wartungsarbeiten wie Komprimierung oder Member-Neuerstellung durchzuführen. Diese Reihenfolge verhindert, dass Sie ein langes Wartungsereignis erstellen, das wenig Speicherplatz zurückgibt.

Verständnis des MongoDB-Festplattenspeicherverbrauchs

MongoDB nutzt Festplattenspeicher für mehrere Komponenten:

  • Datendateien: Speichert die eigentlichen BSON-Dokumente in Sammlungen.
  • Indexdateien: Speichert B-Baum-Indizes, die zur Unterstützung effizienter Abfrageausführung erstellt wurden.
  • Journal-Dateien (WiredTiger): Zeichnet Schreiboperationen auf, bevor sie auf Datendateien angewendet werden, um Datenhaltbarkeit zu gewährleisten. Diese sind vorab zugewiesen.
  • Oplog (Operational Log): Eine spezielle Capped Collection in Replica Sets, die alle Schreiboperationen aufzeichnet. Wesentlich für die Replikation.
  • Diagnosedaten: Logs, mongod-Prozessdateien und andere systembezogene Informationen.

Im Laufe der Zeit können Sammlungen und Indizes aufgrund von Aktualisierungen, Löschungen und Dokumentenwachstum (Padding) fragmentiert werden oder ungenutzten zugewiesenen Speicherplatz enthalten, was zu ineffizienter Festplattennutzung führt. Dieser "Weißraum" wird vom Betriebssystem nicht sofort zurückgewonnen, selbst wenn die Datenbank ihn nicht mehr für Live-Daten benötigt.

Strategien zur Reduzierung des MongoDB-Festplattenspeichers

1. Komprimieren von Sammlungen und Indizes

Komprimierungsvorgänge helfen, ungenutzten Festplattenspeicher zurückzugewinnen, indem Daten- und Indexdateien effizienter neu geschrieben werden. Dies kann besonders nach erheblichen Datenlöschungen oder -aktualisierungen nützlich sein.

Komprimieren von Sammlungen

Mit dem WiredTiger-Speicher-Engine (Standard seit MongoDB 3.2) gewinnt compact hauptsächlich freien Speicherplatz von gelöschten Dokumenten zurück und defragmentiert Sammlungen. Es baut die Datendatei der Sammlung nicht von Grund auf neu auf, wie es die compact-Operation von MMAPv1 tat.

db.runCommand({ compact: "myCollection" })

Überlegungen zu compact:

  • compact-Operationen können ressourcenintensiv (CPU, I/O) sein und viel Zeit in Anspruch nehmen, insbesondere bei großen Sammlungen. Es ist oft am besten, sie während Wartungsfenstern oder auf sekundären Mitgliedern eines Replica Sets auszuführen.
  • Die Festplattenanforderungen und das Sperrverhalten variieren je nach MongoDB-Version, Speicher-Engine und Bereitstellungsform. Überprüfen Sie die Dokumentation für Ihre genaue Version, bevor Sie es auf einer großen Produktionssammlung ausführen.
  • Führen Sie für sharded Cluster compact auf jedem Shard unabhängig aus.

Neuerstellung von Indizes

Indizes können ebenfalls fragmentiert werden. Die Neuerstellung eines Index kann Speicherplatz zurückgewinnen und möglicherweise die Abfrageleistung verbessern.

db.myCollection.reIndex()

reIndex()-Überlegungen:

  • Das Verhalten von reIndex() hat sich über MongoDB-Versionen hinweg geändert und kann auf stark ausgelasteten Systemen immer noch störend sein. Überprüfen Sie das Handbuch für Ihre Version, testen Sie auf der Staging-Umgebung und bevorzugen Sie, wo möglich, die Arbeit über Replica-Set-Mitglieder.
  • Ähnlich wie compact erfordert reIndex() während der Operation zusätzlichen Festplattenspeicher.

repairDatabase (Offline-Operation)

Bei schwerer Fragmentierung oder Datenbeschädigung kann repairDatabase alle Datendateien neu erstellen. Dies ist eine Offline-Operation und erfordert das Stoppen der mongod-Instanz.

mongod --repair

Warnung: repairDatabase sollte nur als letztes Mittel zur Speicherplatzrückgewinnung verwendet werden, da es sich um eine destruktive Operation handelt, wenn sie nicht sorgfältig durchgeführt wird, und sehr lange dauern kann. Halten Sie immer ein Backup bereit.

2. Optimieren von Indizes

Indizes sind entscheidend für die Leistung, können aber erheblichen Festplattenspeicher verbrauchen. Unbenutzte oder redundante Indizes sind reiner Overhead.

Identifizieren und Entfernen unnötiger Indizes

Überprüfen Sie regelmäßig Ihre Indizes, um sicherzustellen, dass sie noch benötigt werden.

  1. Alle Indizes für eine Sammlung auflisten:
    
    

db.myCollection.getIndexes() ``` 2. Indexnutzung überwachen: Verwenden Sie $indexStats, Abfragepläne, Profiling und Ihren Anwendungsworkload-Verlauf. Sammlungsstatistiken zeigen die Indexgröße, beweisen aber nicht, ob ein Index nützlich ist. 3. Doppelte oder redundante Indizes identifizieren: Beispielsweise macht ein Index auf { a: 1, b: 1 } einen Index auf { a: 1 } für Abfragen redundant, die den zusammengesetzten Index verwenden können. Ein Index auf { a: 1, b: 1 } wird auch von einem Index auf { a: 1, b: 1, c: 1 } für Abfragen abgedeckt, die nur a und b betreffen.

Sobald identifiziert, löschen Sie den unbenutzten Index:

db.myCollection.dropIndex("indexName")

Tipp: Testen Sie die Auswirkungen des Löschens eines Index immer in einer Staging-Umgebung, bevor Sie es in der Produktion anwenden.

Verwendung von Partial Indexes

Partial Indexes indizieren nur Dokumente in einer Sammlung, die einen bestimmten Filterausdruck erfüllen. Dies reduziert die Anzahl der indizierten Dokumente, spart Festplattenspeicher und verbessert die Schreibleistung.

db.orders.createIndex(
   { customerId: 1, orderDate: -1 },
   { partialFilterExpression: { status: "active" } }
)

Dieser Index würde nur Dokumente enthalten, bei denen status "active" ist, was seine Größe reduziert, wenn die meisten Bestellungen historisch, storniert, archiviert oder anderweitig außerhalb des Hot Paths sind. Der wichtige Teil ist nicht das Wort "active"; es ist die Gewohnheit, die Teilmenge zu indizieren, die Ihre Anwendung tatsächlich täglich abfragt.

Beginnen Sie mit einer Festplatten-Triage, nicht mit einem Bereinigungsbefehl

Wenn der MongoDB-Festplattenspeicher wächst, ist der erste Fehler, direkt zu compact, repair oder dem Löschen alter Daten zu springen. Diese Aktionen können helfen, aber sie können auch Last erzeugen, in manchen Situationen Sperren verursachen oder das eigentliche Problem für ein paar Wochen verbergen. Beginnen Sie damit, drei Fragen zu beantworten:

  • Welches Dateisystem füllt sich: der Datenbankpfad, der Journal-Pfad, der Log-Pfad oder das Backup-Volume?
  • Wachsen Live-Daten oder wächst zugewiesener, aber ungenutzter Speicherplatz nach Löschungen und Aktualisierungen?
  • Kommt das Wachstum von Sammlungen, Indizes, dem Oplog, Logs, Diagnosedaten oder Snapshots?

Ein schneller erster Durchlauf sieht normalerweise so aus:

df -h
du -h --max-depth=1 /var/lib/mongodb | sort -h
du -h --max-depth=1 /var/log/mongodb | sort -h

Überprüfen Sie dann MongoDB von der Shell aus:

db.adminCommand({ listDatabases: 1 })
db.getSiblingDB("app").stats()
db.getSiblingDB("app").orders.stats()

storageSize, totalIndexSize und dataSize erzählen unterschiedliche Geschichten. Wenn dataSize wächst, haben Sie wahrscheinlich ein Problem mit dem Datenlebenszyklus. Wenn storageSize viel größer als dataSize ist, sehen Sie möglicherweise wiederverwendbaren internen Speicherplatz nach Löschungen. Wenn totalIndexSize im Vergleich zu dataSize groß ist, verdient das Indexdesign Aufmerksamkeit, bevor Sie die Komprimierung anfassen.

Verstehen, was MongoDB zurückgeben kann und was nicht

Mit WiredTiger macht das Löschen von Dokumenten normalerweise Speicherplatz für die Wiederverwendung durch MongoDB verfügbar. Es gibt diesen Speicherplatz nicht immer sofort an das Betriebssystem zurück. Dieses Verhalten überrascht Leute während der Notfallbereinigung: Sie löschen einen großen Batch, führen df -h aus und sehen fast keine Verbesserung.

Das bedeutet nicht, dass das Löschen fehlgeschlagen ist. Es bedeutet, dass MongoDB diesen Speicherplatz oft für zukünftige Einfügungen und Aktualisierungen wiederverwenden kann. Wenn das Ziel darin besteht, das Wachstum zu stoppen, kann das Löschen oder Archivieren alter Daten ausreichen. Wenn das Ziel darin besteht, das Dateisystem zu verkleinern, weil das Volume fast voll ist oder der Host verkleinert wird, benötigen Sie möglicherweise eine Komprimierung, eine erneute Synchronisierung eines Replica-Set-Mitglieds oder eine Dump-and-Restore-Neuerstellung.

Für Produktionssysteme trenne ich die Arbeit normalerweise in zwei Spuren. Die erste Spur ist die sofortige Sicherheit: Festplatte hinzufügen, offensichtliche Log-Ansammlungen entfernen, riskante Batch-Jobs pausieren oder Backups vom Datenbank-Volume verschieben. Die zweite Spur ist die echte Reduzierung: Aufbewahrung reparieren, unbenutzte Indizes entfernen und Speicher erst neu aufbauen, nachdem Sie wissen, wohin die Bytes gegangen sind.

Reparieren Sie die Datenaufbewahrung, bevor Sie etwas defragmentieren

Wenn Ihre Anwendung Anfrageprotokolle, Ereignisse, Sitzungen, Benachrichtigungen, Jobaufzeichnungen oder Analysedokumente für immer behält, wird der Festplattenverbrauch zurückkehren, egal wie sorgfältig Sie komprimieren. MongoDB bietet Ihnen einige praktische Optionen.

Für Daten, die basierend auf einem einfachen Zeitstempel ablaufen, ist ein TTL-Index oft die sauberste Antwort:

db.sessions.createIndex(
  { expiresAt: 1 },
  { expireAfterSeconds: 0 }
)

Dieser Index entfernt Dokumente nach dem in expiresAt gespeicherten Datum. Er ist nützlich für Sitzungen, temporäre Tokens, kurzlebige Import-Jobs oder zwischengespeicherte API-Antworten. Er ist kein Ersatz für Geschäftsaufbewahrungsregeln. Der TTL-Monitor läuft im Hintergrund, erwarten Sie also keine sekundengenaue Löschung, und verwenden Sie TTL nicht für Daten, die vor dem Löschen einen Genehmigungsworkflow erfordern.

Für Geschäftsaufzeichnungen archivieren Sie, anstatt blind zu löschen. Ein häufiges Muster ist:

  1. Kopieren Sie Dokumente, die älter als das Aufbewahrungsfenster sind, in günstigeren Speicher oder eine Archivdatenbank.
  2. Überprüfen Sie die Anzahl und eine Stichprobe wichtiger Felder.
  3. Löschen Sie in kleinen Batches aus der primären Sammlung.
  4. Beobachten Sie die Replikationsverzögerung und Festplattenmetriken, während der Job läuft.

Kleine Batches sind wichtig. Ein einzelner großer Löschvorgang kann Replikationsdruck erzeugen, Logs füllen und das Rollback erschweren, wenn jemand erkennt, dass der Filter falsch war. Ein sichererer Batch-Job könnte jeweils ein paar tausend Dokumente löschen, kurz pausieren und den Fortschritt nach _id oder Zeitstempel aufzeichnen.

while (true) {
  const result = db.events.deleteMany({
    createdAt: { $lt: ISODate("2025-01-01T00:00:00Z") },
    archived: true
  });

  print(`deleted ${result.deletedCount}`);
  if (result.deletedCount === 0) break;
  sleep(500);
}

Fügen Sie in einem echten Produktionsskript ein Limit-Muster anstelle von deleteMany über den gesamten Bereich hinzu, protokollieren Sie jeden Batch und stoppen Sie automatisch, wenn die Replikationsverzögerung oder der Festplatten-I/O Ihren Schwellenwert überschreitet.

Seien Sie vorsichtig mit Index-Ratschlägen, die zu einfach klingen

Das Löschen unbenutzter Indizes ist eine der besten Möglichkeiten, den MongoDB-Festplattenspeicher zu reduzieren, aber "unbenutzt" braucht Kontext. Ein Index mag in einer ruhigen Woche unbenutzt aussehen und dennoch kritisch für Monatsendberichte, Hintergrundabgleiche oder einen seltenen Kundensupport-Workflow sein.

Verwenden Sie $indexStats, um Zugriffsmuster zu sehen:

db.orders.aggregate([{ $indexStats: {} }])

Vergleichen Sie dann das Ergebnis mit Anwendungscode, geplanten Jobs, Dashboards und Support-Abfragen. Wenn ein Index seit dem letzten Neustart nicht verwendet wurde, ist das ein Signal, kein Urteil. Bevor Sie ihn löschen, überprüfen Sie, ob der Server kürzlich neu gestartet wurde und ob die Workload-Stichprobe die Jobs enthält, die wichtig sind.

Achten Sie auch auf überlappende zusammengesetzte Indizes. Wenn Sie diese haben:

{ customerId: 1 }
{ customerId: 1, createdAt: -1 }
{ customerId: 1, createdAt: -1, status: 1 }

können Sie möglicherweise einen entfernen, aber nur nach Überprüfung der Sortierreihenfolge, Abfragefilter und ob der kürzere Index ein anderes Zugriffsmuster unterstützt. MongoDB kann das linke Präfix eines zusammengesetzten Index verwenden, aber das bedeutet nicht, dass der größte Index immer ein kostenloser Ersatz ist. Größere Indizes kosten mehr Speicher und Schreib-I/O, behalten Sie also den, der zum Workload passt, nicht den, der am vollständigsten aussieht.

Bevorzugen Sie Resync für große Schrumpfoperationen auf Replica Sets

Für ein großes Replica Set ist der sauberste Weg, Betriebssystem-Festplattenspeicher zurückzugewinnen, oft, ein sekundäres Mitglied nach dem anderen neu zu erstellen. Die Grundidee ist:

  1. Bestätigen Sie, dass Sie eine gesunde Replikation und aktuelle Backups haben.
  2. Entfernen oder stoppen Sie ein sekundäres Mitglied.
  3. Löschen Sie sein lokales Datenverzeichnis.
  4. Lassen Sie es vom primären oder einem anderen gesunden Mitglied neu synchronisieren.
  5. Wiederholen Sie dies für das nächste sekundäre Mitglied.
  6. Stufen Sie das primäre Mitglied während eines Wartungsfensters herab und erstellen Sie das alte primäre Mitglied zuletzt neu.

Dieser Ansatz ist langsamer als das Ausführen eines Befehls, aber einfacher zu durchdenken, da jedes neu erstellte Mitglied frische Speicherdateien basierend auf aktuellen Daten schreibt. Er vermeidet auch den Versuch, jede Sammlung unter Produktionslast zu komprimieren. Er ist nicht kostenlos: Die initiale Synchronisierung kann netzwerk- und festplattenintensiv sein, und Sie benötigen genügend verbleibende Mitglieder, um das Replica Set sicher zu halten, während ein Mitglied neu erstellt wird.

Für einen eigenständigen MongoDB-Server haben Sie diesen Luxus nicht. Planen Sie in diesem Fall ein Wartungsfenster, erstellen Sie ein getestetes Backup und erwägen Sie mongodump/mongorestore oder eine Migration auf Dateisystemebene auf ein neues Volume. Wählen Sie nicht mongod --repair, nur weil Sie ein kleineres Datenverzeichnis möchten. Behandeln Sie die Reparatur als Wiederherstellungswerkzeug, nicht als routinemäßige Hausarbeit.

Beobachten Sie auch Oplog, Logs und Backups

Nicht jeder MongoDB-Festplattendruck kommt von Sammlungen. In Replica Sets ist der Oplog eine Capped Collection, sollte also nicht ewig wachsen, aber seine konfigurierte Größe ist dennoch wichtig. Wenn er zu klein ist, können sekundäre Mitglieder während der Wartung abfallen. Wenn er auf einer kleinen Festplatte viel größer als nötig ist, verschwendet er möglicherweise Speicherplatz. Überprüfen Sie ihn bewusst:

db.getSiblingDB("local").oplog.rs.stats()

MongoDB-Logs können ebenfalls eine Festplatte füllen, wenn die Protokollierung langsamer Abfragen, die Debug-Ausführlichkeit oder eine Anwendungsfehlerschleife laut wird. Verwenden Sie Log-Rotation und halten Sie Datenbank-Logs nach Möglichkeit vom selben kleinen Volume fern, das Daten speichert.

Backups sind eine weitere häufige Überraschung. Teams führen manchmal mongodump auf demselben Host aus, weil es bequem ist, und fragen sich dann, warum Festplattenwarnungen während des Backup-Fensters ausgelöst werden. Ein Backup, das auf demselben Dateisystem gespeichert ist, ist nicht wirklich ein Backup und kann MongoDB während einer bereits riskanten Operation in einen schlimmeren Ausfall treiben. Streamen Sie Backups in den Objektspeicher, auf einen Backup-Server oder ein separates gemountetes Volume.

Ein praktisches Runbook für eine volle MongoDB-Festplatte

Wenn die Festplatte bereits über 90 Prozent ist, verlangsamen Sie und arbeiten Sie in dieser Reihenfolge:

  1. Bestätigen Sie, ob MongoDB noch Schreibvorgänge akzeptiert und ob das Replica Set gesund ist.
  2. Fügen Sie temporäre Festplattenkapazität hinzu, wenn die Plattform dies zulässt. Dies ist oft sicherer als eine Notlöschung.
  3. Verschieben oder rotieren Sie übermäßig große Logs und lokale Backup-Dateien.
  4. Stoppen Sie nicht wesentliche Batch-Jobs, die stark schreiben.
  5. Identifizieren Sie die größten Sammlungen und Indizes mit db.stats() und Sammlungs-stats().
  6. Archivieren oder löschen Sie nur Daten mit einer klaren Aufbewahrungsregel.
  7. Planen Sie Komprimierung, Resync oder Wiederherstellung, nachdem das System stabil ist.

Die beste langfristige Lösung ist langweilig: Aufbewahrungsregeln, Indexüberprüfungen, Festplattenwarnungen und getestete Neuerstellungsverfahren. MongoDB ist bequem darin, internen freien Speicherplatz wiederzuverwenden, aber Betreiber müssen dennoch entscheiden, welche Daten es verdienen, auf schnellem Speicher zu leben und was woanders hin verschoben werden kann.