Seitenanfang

MongoDB Stresstest - und neue Probleme

Dieser Post wurde aus meiner alten WordPress-Installation importiert. Sollte es Darstellungsprobleme, falsche Links oder fehlende Bilder geben, bitte einfach hier einen Kommentar hinterlassen. Danke.


Vor Kurzem habe ich MongoDB getestet und zum ersten Mal in einem (kleinen) Projekt eingesetzt. Jetzt, beim nächsten neuen Projekt, sollte die neue NoSQL Datenbank wieder zum Einsatz kommen. In diesem Fall muss allerdings mit mindestens einer Million Einträge pro Collection gerechnet werden und vor der endgültigen Entscheidung musste MongoDB zeigen, ob es dem Ansturm gewachsen ist.Dazu habe ich ein einfaches Perl-Script benutzt, dass obendrein YAWF::Object::MongoDB, meinen Abstraktionslayer, verwendet um eventuelle Probleme im Gesamtkonstrukt zu erkennen:
perl -Mt::lib::Car -e '$|=1; for (1..1000) { print "$_\r"; for (1..1000) { my $o = t::lib::Car->new; $o->model($_); $o->flush; } }'
Der Perl Oneliner durchläuft 1.000.000 Zyklen (1000 x 1000) und erstellt jeweils ein neues Dokument in einer der Datenbanken, die bereits von den Test-Scripten verwendet wird.

Der Test lief auf meiner Workstation (Celeron 3,2 GHz) mit gleichzeitig laufendem X und einigen Programmen.

Auch der letzte 1.000er Block wurde ohne sichtbare Zeitverzögerung geschrieben, der MongoDB-Daemon verbrauchte dabei weniger als 20% CPU-Last und erstaunlich wenig RAM.

Als nächstes habe ich den Test um eine quantitative Messung erweitert, um den gefühlten Wert (keine Zeitverzögerung auch nach 1 Mio. Einträgen) auch objektiv zu beweisen:

perl -Ilib -Mt::lib::Car -MTime::HiRes -e '$|=1; for (1..10) { print "$_\r"; my $s = Time::HiRes::time; for (1..100000) { my $o = t::lib::Car->new; $o->model($_); $o->flush; } print "\t".(Time::HiRes::time - $s)."\n"; }'
Es bleibt bei 1.000.000 neuen Dokumenten, diesmal allerdings 10 x 100.000, zudem wird die für jeden 100.000-Block benötigte Zeit ausgegeben. Während die normale Perl-"time"-Funktion einen Integer zurückgibt, liefert Time::HiRes::time einen Fließkommawert, damit lassen sich auch Werte unter einer Sekunde messen. Die Zahlen bestätigten meine gefühlten Werte:

1       44.20529198646552       45.5772418975833       44.70065283775334       44.03454184532175       45.24184608459476       44.07931804656987       42.3029620647438       44.88365316390999       47.331378936767610     44.6474239826202

Die Schwankungen zwischendurch dürften den sonstigen Belastungen meiner Workstation geschuldet sein, denn Webbrowser & Co. fordern auch ihren Anteil der CPU. MongoDB benötigt inklusive Abstraktion, Schnittstelle & Co. insgesamt etwa 420ns bis 470ns (0,00042 bzw. 0,00047 Sekunden) pro neuem Dokument, das entspricht etwa 127.000 bis 142.000 Dokumenten pro Minute.

Viel wichtiger war die Frage, ob MongoDB mit dieser Datenmenge auch umgehen kann. Nach verschiedenen (z.T. abgebrochenen) Testläufen liegen zur Zeit 2.943.930 Dokumente in der Test-Collection. Die count() - Abfrage lieferte diese Zahl sofort, ohne sichtbare Verzögerung, ebenso reagierte ein find({ model: 735 }) und das, obwohl "model" noch nicht einmal über einen Index verfügt!

Meine Testreihe habe ich an dieser Stelle beendet, denn die Ergebnisse waren (auf meiner altersschwachen Workstation!) bereits überwältigend - und mit 3 Mio. Einträgen liegt die Test-Collection bereits weit über den im neuen Projekt erwarteten Zahlen. Im "täglichen Leben" dürfte diese Zahl auch bei kaum einem Projekt erreicht werden, egal ob es sich um ein gut besuchtes Forum oder ein (semiprofessionelles) Browserspiel handelt.

 

2 Kommentare. Schreib was dazu

  1. sonyon

    Das klingt interessant, allerdings frage ich mich inwieweit das in echten Szenarien mit groesseren Dokumenten greifen würde.


    Wo du grade das Beispiel bringst. Meinst du ein Forum wäre mit Mongodb praktikabel? Das würde ja im Prinzip ganz neue Möglichkeiten bringen.

  2. Sebastian

    Ja, absolut!
    Vernünftig programmiert könnten die Thread-Daten auf der obersten Ebene des Trees liegen und die Posts einfach in ein Array geschrieben werden. Ruft jetzt jemand den Thread auf, werden nur die "Headerdaten" und ggf. die passenden Posts für die aktuell anzuzeigende Seite geladen, dann wäre jeder Thread ein Dokument. Neue Posts werden einfach ran ge-push()-ed, fertig.

Schreib was dazu

Die folgenden HTML-Tags sind erlaubt:<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>