Ich habe das folgende Mongoengine-Modell:
%Vor%In einigen Fällen kann das Dokument in der DB sehr groß sein (etwa 5-10 MB), und die data_dict-Felder enthalten komplexe verschachtelte Dokumente (Diktatlisten, usw.).
Ich habe zwei (möglicherweise verwandte) Probleme festgestellt:
Wenn ich ein einzelnes großes Dokument aus der Datenbank abfrage und dann auf sein Feld zugreife, dauert es nur 10-20 Sekunden, um Folgendes zu tun:
%Vor% Die Daten im Objekt enthalten keine Verweise auf andere Objekte, daher ist es kein Problem der Dereferenzierung von Objekten.
Ich vermute, dass es mit einer Ineffizienz der internen Datendarstellung von Mongoengine zusammenhängt, die sowohl die Konstruktion des Dokumentobjekts als auch den Zugriff auf Felder beeinflusst. Kann ich etwas tun, um das zu verbessern?
TL; DR: mongoengine veraltet sich und konvertiert alle zurückgegebenen Arrays in dicts
Um dies zu testen, habe ich eine Sammlung mit einem Dokument mit einem DictField
mit einem großen verschachtelten dict
erstellt. Das Dokument liegt ungefähr im Bereich von 5-10 MB.
Wir können dann timeit.timeit
verwenden, um den Unterschied bei den Lesevorgängen mit Pymongo und Mongoengine zu bestätigen.
Wir können dann pycallgraph und GraphViz um zu sehen, was mongoengine so verdammt lange dauert.
Hier ist der vollständige Code:
%Vor%Und die Ausgabe beweist, dass Mongoengine im Vergleich zu Pymongo sehr langsam ist:
%Vor%Das resultierende Call-Diagramm zeigt ziemlich deutlich, wo der Flaschenhals ist:
Im Wesentlichen wird Mongoengine die Methode to_python für jedes DictField
aufrufen, das es von der Datenbank zurückerhält. to_python
ist ziemlich langsam und in unserem Beispiel wird es eine wahnsinnige Anzahl von Malen genannt.
Mongoengine wird verwendet, um Ihre Dokumentstruktur elegant Python-Objekten zuzuordnen. Wenn Sie sehr große unstrukturierte Dokumente haben (für die mongodb ist großartig), dann Mongoengine ist nicht wirklich das richtige Werkzeug und Sie sollten nur Pymongo verwenden.
Wenn Sie jedoch die Struktur kennen, können Sie EmbeddedDocument
-Felder verwenden, um eine etwas bessere Leistung von mongoengine zu erhalten. Ich habe einen ähnlichen, aber nicht äquivalenten Test Code in diesem Gist ausgeführt und die Ausgabe ist:
Damit kannst du Mongoengine schneller machen, aber Pymongo ist noch viel schneller.
AKTUALISIEREN
Eine gute Abkürzung zur Pymongo-Schnittstelle ist hier das Aggregation Framework:
%Vor%Tags und Links python mongodb pymongo mongoengine