2013-07-19 3 views
15

Ich muss mehrere Milliarden kleine Datenstrukturen (jeweils etwa 200 Bytes) speichern. Bisher funktioniert das Speichern jedes Elements als separates Dokument gut, wobei Mongo etwa 10.000 Ergebnisse pro Sekunde liefert. Ich verwende einen 20-Byte-Hash als _id für jedes Dokument und einen einzelnen Index für das _id-Feld. Im Test funktioniert das für Datensätze mit 5.000.000 Dokumenten.Strategien für die schnelle Suche von Milliarden von kleinen Dokumenten in MongoDB

Im Betrieb werden wir etwa 10.000 Anfragen pro Sekunde machen, bestehende Dokumente etwa 1.000 Mal pro Sekunde aktualisieren und neue Dokumente vielleicht 100 Mal pro Sekunde oder weniger einfügen.

Wie können wir größere Datensätze verwalten, wenn wir nicht einen ganzen Index im RAM speichern können? Wird MongoDB besser funktionieren, wenn wir mehrere Elemente in jedes Dokument kombinieren - für eine schnellere Suche durch den Index, aber mehr Daten, die in jeder Abfrage zurückgegeben werden?

Im Gegensatz zu anderen Fragen zu SO bin ich nicht nur daran interessiert, wie viele Daten wir in Mongo stopfen können. Es kann die Datenmenge, die wir uns ansehen, klar verwalten. Meine Sorge ist, wie können wir die Geschwindigkeit von find Operationen auf riesige Sammlungen, bei eingeschränktem RAM maximieren.

Unsere Suchen werden tendenziell geclustert sein; Etwa 50.000 Elemente werden ungefähr 50% der Abfragen erfüllen, die restlichen 50% werden jedoch zufällig auf alle Daten verteilt. Können wir einen Leistungszuwachs erwarten, indem wir diese 50% in ihre eigene Sammlung verschieben, um einen kleineren Index der am häufigsten verwendeten Daten immer in RAM zu behalten?

Würde die Reduzierung der Größe des Felds _id von 20 auf 8 Byte einen wesentlichen Einfluss auf die Indizierungsgeschwindigkeit von MnogoDB haben?

+0

Da es sich anhört, als hätten Sie weit mehr Dokumente als RAM, würde ich die Dokumente so weit wie möglich verkleinern, um die Datenmenge zu erhöhen, die in den RAM passen kann. Stellen Sie sicher, dass Feldnamen nur aus einem oder zwei Zeichen bestehen. Planen Sie Sharding? Das Verschieben von Daten in eine bestimmte Sammlung auf demselben Server ändert nicht die RAM-Nutzung, da das Betriebssystem ohnehin verwaltet wird. – WiredPrairie

+0

Wir werden sharding sein, wenn die Daten wachsen. – Neil

+0

Es ist nur eine Idee, die am häufigsten verwendeten Datensätze in eine andere Sammlung zu stellen, um den Index für diese kleinere Sammlung im RAM zu behalten und zu verhindern, dass sie ausgelagert wird. Ich denke, das könnte naiv sein, aber ich bin mir nicht sicher warum oder warum nicht. – Neil

Antwort

17

Einige Strategien in den Sinn kommen:

1) eine eindeutige Sammlung/Datenbank für die ‚heiße‘ Dokumente.

Wenn Sie wissen, welche Dokumente im Hot Set sind, dann hilft das Verschieben in eine separate Sammlung. Dadurch wird sichergestellt, dass die Hot-Dokumente in denselben Bereichen/Seiten gemeinsam resident sind. Dadurch wird auch der Index für diese Dokumente wahrscheinlicher vollständig im Speicher gespeichert. Dies liegt daran, dass es kleiner ist und (vollständig?) Häufiger verwendet wird.

Wenn die Hot-Dokumente nach dem Zufallsprinzip mit anderen Dokumenten gemischt werden, müssen Sie wahrscheinlich mehr Blattelemente des B-Tree-Indexes beim Laden eines Dokuments als Wahrscheinlichkeit eines kürzlich geladenen oder auf den Index zugegriffenen anderen Dokuments angeben Block ist klein.

2) Kürzen Sie die indizierten Werte.

Je kürzer der Indexwert, desto mehr Werte passen in einen einzelnen B-Tree-Block. (Hinweis: Die Schlüssel sind nicht im Index enthalten.) Je mehr Einträge in einem einzelnen Bucket enthalten sind, desto weniger Buckets und weniger Gesamtspeicher für den Index. Das bedeutet eine höhere Wahrscheinlichkeit/längere Lebensdauer, dass die Blöcke im Speicher bleiben. In Ihrem Beispiel ist eine Reduzierung um 20-> 8 Zeichen eine Ersparnis von mehr als 50%. Wenn Sie diese 8 Bytes zu einem langen konvertieren können, gibt es ein wenig mehr Einsparungen, da longs kein Längenpräfix (4 Bytes) und ein abschließendes Null (5 Bytes insgesamt) haben.

3) Kürzen Sie die Schlüsselnamen.

Je kürzer das Feld ist, desto weniger Platz beansprucht jedes Dokument. Dies hat den unglücklichen Nebeneffekt, die Lesbarkeit zu verringern.

4) Shard

Das ist wirklich der einzige Weg, die Leistung bis ins Gesicht halten von über einen gesamten Korpus liest, die Speicher und eventuelle Festplattenbandbreite erschöpft. Wenn du Shard machst, willst du immer noch die "heiße" Sammlung sharden.

5) Adjust the read-ahead on disk to a small value.

Da die ‚Nicht-hot‘, heißt es werden ein zufälliges Dokument von der Festplatte laden wir wirklich nur lesen wollen/Fehler in den Speicher, der wie möglich um sie zu dokumentieren und als einige der Dokumente. Die meisten Systeme werden versuchen, einen großen Datenblock zu lesen, sobald ein Benutzer aus einem Teil einer Datei liest. Das ist genau das Gegenteil von dem, was wir wollen.

Wenn Sie feststellen, dass Ihr System stark gestört ist, aber der residente Speicher für den mongod-Prozess sich nicht an den verfügbaren Speicher des Systems annähert, sehen Sie wahrscheinlich den Effekt, dass das Betriebssystem nutzlose Daten liest.

6) Versuchen Sie monoton steigende Werte für die Tasten zu verwenden.

Dies wird eine Optimierung auslösen (für ObjectId-basierte Indizes), die bei der Teilung des Indexblocks bei 90/10 statt 50/50 erfolgt. Das Ergebnis ist, dass die meisten Blöcke in Ihrem Index fast voll sind und Sie weniger davon benötigen.

Wenn Sie nur die "heißen" 50.000 Dokumente nach der Tat kennen, dann wird das Hinzufügen dieser Objekte zur separaten Sammlung in Indexreihenfolge auch diese Optimierung auslösen.

Rob.

Verwandte Themen