Was ist ein Cursor in MongoDB?
Wir sind beunruhigt durch eventuell auftretende cursor not found exceptions
für einige Morphia Abfragen asList
und ich habe ein Hinweis auf SO, dass dies vielleicht ganz Recht sein, Speicher kräftezehrend ist.
Nun würde ich gerne wissen, ein wenig mehr über den hintergrund: kann sombody erklären (in Englisch), welche einen Cursor (in MongoDB) eigentlich ist? Warum kann er offen gelassen oder nicht gefunden werden?
In der Dokumentation definiert einen cursor als:
Einen Zeiger auf die Ergebnismenge einer Abfrage. Kunden können Durchlaufen eines Cursors, abrufen von Ergebnissen. Standardmäßig Cursor timeout nach 10 Minuten Inaktivität
Aber das ist nicht sehr aufschlussreich. Vielleicht könnte es hilfreich sein, zu definieren, eine batch
für Abfrage-Ergebnisse, da die Dokumentation auch Staaten:
Den MongoDB-server gibt die Ergebnisse der Abfrage in den Reihen. Batch-Größe wird nicht mehr als die maximale BSON-Dokument Größe. Für die meisten Abfragen, die erste Partie gibt 101 Dokumente oder einfach nur genug Dokumente, um mehr als 1 megabyte. Nachfolgende batch-Größe von 4 Megabyte. [...] Für Abfragen, die eine Art operation ohne index, den server laden muss, werden alle Dokumente im Speicher zum durchführen des sortiervorgangs vor etwaiger Rücksendung der Ergebnisse.
Hinweis: in unserem Abfragen in Frage, die wir nicht verwenden, Sortieren von Aussagen, aber auch keine limit
und offset
.
- Ich meine, dass deine Frage wandert das Thema ab, sollten Sie sich Fragen, über. Wenn Sie tatsächlich empfangen "cursor wurde nicht gefunden" Ausnahmen, dann Frage bei Fehler Ihres implementierten code. Eine breitere Diskussion darüber, was ein cursor "eigentlich" ist mehr eine "breitere design-Frage" als etwas, das löst eine spezifische Programmierung problem, wie das, was diese Seite ist, Also "zu viel schimpfen über Cursor, und nicht genug code, der könnte das Problem verursachen". So wie es da steht, deine Frage sieht aus wie es ist zu Fragen, für eine these, die erklären, was ein cursor ist. Nur zeigen einige code.
- Der Punkt ist, dass das auftreten dieser Ausnahmen hängt von der Umgebung ab. Wir derzeit nicht wissen, welcher parameter (Speicher, CPU, whatever) ist entscheidend. Deshalb bin ich daran interessiert, einige hintergrund. Unser code sieht wie
ds.find(Translation.class).asList()
(ds Morphia.Datastrore). - Wenn Sie mongo in einer Replik setzen Sie den cursor, wird verloren sein, wenn Ihre Server entscheidet, auf einer anderen primären Knoten.
- Sie sind so wahr. Sie brauchen eine
seed list
von Servern, verwenden Sie niemals Ihr eigenes load-balancing-Lösung. Beschreibung hier.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Ich bin auf keinen bedeutet eine mongodb Experte, aber ich möchte nur hinzufügen, dass einige Beobachtungen aus der Arbeit in einem mittelständischen mongo-system für das Letzte Jahr. Auch Dank an @xameeramir für die hervorragende walkthough darüber, wie Cursor die Arbeit im Allgemeinen.
Den Ursachen des "cursor lost" Ausnahme kann mehrere. Eine, die ich bemerkt habe ist, erklärte in dieser Antwort.
Den cursor lebt der server-Seite. Es ist nicht verteilt über ein Replikat festgelegt, sondern besteht auf die Instanz, die primär auf die Zeit der Schöpfung. Dies bedeutet, dass, wenn eine andere Instanz übernimmt primär den cursor, wird verloren sein, an den client. Wenn die alte Grundschule ist immer noch, und um es möglicherweise noch gibt es aber keine Verwendung. Ich denke, es ist garbaged gesammelt Weg nach einer Weile. Also, wenn Ihr mongo Replikatgruppe ist instabil oder haben Sie einen wackeligen Netzwerk vor, Sie sind aus Glück heraus, wenn dabei die lang andauernde Abfragen.
Wenn der volle Inhalt von dem, was Sie den cursor will wieder nicht in den Speicher passt auf die server kann die Abfrage sehr langsam sein. RAM auf Ihrem Server muss größer sein als die größte Abfrage, die Sie ausführen.
All dies kann teilweise vermieden werden können, von der Gestaltung besser. Für eine Verwendung bei großen lange ausführen von Abfragen Sie können besser mit mehreren kleineren Datenbank-Sammlungen statt ein großes.
Hier ist ein Vergleich zwischen
toArray()
und Cursor nachfind()
im Node.js MongoDB-Treiber. Common code:Hier ist die
toArray()
code, geht in den Abschnitt oben.Pro die Dokumentation,
Hier ist die cursor-basierten Ansatz, mit dem die
cursor.forEach()
Methode:Mit der
forEach()
Ansatz, anstelle von abrufen alle Daten im Speicher, sind wir ein streaming der Daten in unserer Anwendung.find()
wird ein cursor sofort, weil es eigentlich nicht machen, eine Anfrage an die Datenbank, bis wir versuchen, einige der Dokumente, die es zur Verfügung stellt. Der Punkt, dercursor
ist die Beschreibung unserer Abfrage. Der zweite parametercursor.forEach
zeigt, was zu tun ist, wenn ein Fehler Auftritt.In der ersten version des obigen code, es war
toArray()
das Zwang die Datenbank aufrufen. Es bedeutete, wir brauchten ALLE die Dokumente und wollte, dass Sie in einemarray
.Beachten Sie, dass
MongoDB
gibt Daten in den Reihen. Das Bild unten zeigt die Anforderungen von Cursorn (von der Anwendung) zuMongoDB
:forEach
besser skaliert alstoArray
denn wir können bei der Verarbeitung von Dokumenten , wie Sie kommen in, bis wir das Ende erreichen. Dagegen ist Sie mittoArray
- wo wir warten ALLE die Dokumente werden abgerufen und die gesamte array aufgebaut ist. Dies bedeutet, dass wir nicht immer einen Vorteil aus der Tatsache, dass die Treiber und der Datenbank-Systems arbeiten zusammen, um batch Ergebnisse zu Ihrer Anwendung. Die Dosierung soll die Effizienz in Bezug auf Speicherbedarf und die Ausführungszeit. Nutzen Sie es in Ihrer Anwendung, wenn Sie kann.Dieser Fehler kommt auch, wenn man eine große Menge von Daten und batch-Verarbeitung der Daten und jede Partie dauert länger, als den Standard-cursor-live-Zeit.
Dann müssen Sie ändern, die default-Zeit zu sagen, "mongo", die nicht verfallen diese cursor, bis Verarbeitung fertig ist.
Do-check - Es Wird Kein TimeOut-Dokumentation