Wie sortiert MongoDB Datensätze, wenn keine Sortierreihenfolge angegeben ist?

102

Was verwendet die Datenbank intern, um die Ergebnisse zu sortieren, wenn wir eine Mongo find () - Abfrage ohne Angabe einer Sortierreihenfolge ausführen?

Laut der Dokumentation auf der Mongo-Website :

Wenn Sie find () ohne Parameter ausführen, gibt die Datenbank Objekte in natürlicher Vorwärtsreihenfolge zurück.

Für Standardtabellen ist die natürliche Reihenfolge nicht besonders nützlich, da die Reihenfolge zwar oft nahe an der Einfügereihenfolge liegt, dies jedoch nicht garantiert ist. Bei begrenzten Sammlungen ist jedoch garantiert, dass die natürliche Reihenfolge die Einfügereihenfolge ist. Dies kann sehr nützlich sein.

Welches Feld wird jedoch für Standardsammlungen (nicht begrenzte Sammlungen) zum Sortieren der Ergebnisse verwendet? Ist es das _id- Feld oder etwas anderes?

Bearbeiten:

Grundsätzlich denke ich, dass ich versuche, das zu erreichen, wenn ich die folgende Suchabfrage ausführe:

db.collection.find({"x":y}).skip(10000).limit(1000);

Zu zwei verschiedenen Zeitpunkten: t1 und t2 erhalte ich unterschiedliche Ergebnismengen:

  1. Wenn zwischen t1 und t2 keine zusätzlichen Schreibvorgänge stattgefunden haben?
  2. Wann gab es neue Schreibvorgänge zwischen t1 und t2?
  3. Es gibt neue Indizes, die zwischen t1 und t2 hinzugefügt wurden.

Ich habe einige Tests in einer temporären Datenbank durchgeführt und die Ergebnisse, die ich erhalten habe, sind für alle drei Fälle gleich ( Ja ) - aber ich wollte sicher sein und bin mir sicher, dass meine Testfälle nicht sehr gründlich waren.

saurabhj
quelle

Antworten:

120

Was ist die Standardsortierreihenfolge, wenn keine angegeben ist?

Die standardmäßige interne Sortierreihenfolge (oder natürliche Reihenfolge ) ist ein undefiniertes Implementierungsdetail. Aufrechterhaltung der Ordnung ist zusätzliche Aufwand für Speicher - Engines und MongoDB API nicht Vorhersagbarkeit außerhalb eines ausdrücklichen Auftrag sort()oder den Sonderfall fester Größe mit einer Kappe bedeckt Sammlungen , die verknüpft sind Nutzungsbeschränkungen . Für typische Workloads ist es wünschenswert, dass die Speicher-Engine versucht, den verfügbaren vorab zugewiesenen Speicherplatz wiederzuverwenden und Entscheidungen darüber zu treffen, wie Daten am effizientesten auf der Festplatte und im Speicher gespeichert werden.

Ohne Abfragekriterien werden die Ergebnisse von der Speicher-Engine in natürlicher Reihenfolge (auch bekannt als in der Reihenfolge, in der sie gefunden wurden ) zurückgegeben. Die Ergebnisreihenfolge kann mit der Einfügereihenfolge übereinstimmen, dieses Verhalten ist jedoch nicht garantiert und kann nicht verwendet werden (abgesehen von begrenzten Sammlungen).

Einige Beispiele, die die (natürliche) Speicherreihenfolge beeinflussen können:

  • WiredTiger verwendet eine andere Darstellung von Dokumenten auf der Festplatte als der speicherinterne Cache, sodass sich die natürliche Reihenfolge aufgrund interner Datenstrukturen ändern kann.
  • Die ursprüngliche MMAPv1-Speicher-Engine (in MongoDB 4.2 entfernt) weist Datensatzspeicherplatz für Dokumente basierend auf Auffüllregeln zu. Wenn ein Dokument über den aktuell zugewiesenen Datensatzbereich hinauswächst, wird der Dokumentspeicherort (und die natürliche Reihenfolge) beeinflusst. Neue Dokumente können auch in den Speicher eingefügt werden, der aufgrund gelöschter oder verschobener Dokumente als zur Wiederverwendung verfügbar markiert ist.
  • Die Replikation verwendet ein idempotentes Oplog- Format, um Schreibvorgänge konsistent auf Replikatsatzmitglieder anzuwenden. Jedes Replikatsatzmitglied verwaltet lokale Datendateien, die in natürlicher Reihenfolge variieren können, aber das gleiche Datenergebnis haben, wenn Oplog-Updates angewendet werden.

Was ist, wenn ein Index verwendet wird?

Wenn ein Index verwendet wird, werden Dokumente in der Reihenfolge zurückgegeben, in der sie gefunden wurden (was notwendigerweise der Einfügereihenfolge oder der E / A-Reihenfolge entspricht). Wenn mehr als ein Index verwendet wird, hängt die Reihenfolge intern davon ab, welcher Index das Dokument während des Deduplizierungsprozesses zuerst identifiziert hat.

Wenn Sie eine vorhersagbare Sortierreihenfolge Sie müssen eine explizite sind sort()mit Ihrer Anfrage und haben eindeutige Werte für die Sortierschlüssel.

Wie behalten begrenzte Sammlungen die Einfügereihenfolge bei?

Die Implementierungsausnahme, die für die natürliche Reihenfolge in mit einer Kappe versehenen Sammlungen angegeben ist, wird durch ihre besonderen Verwendungsbeschränkungen erzwungen: Dokumente werden in der Einfügereihenfolge gespeichert, die vorhandene Dokumentgröße kann jedoch nicht erhöht und Dokumente können nicht explizit gelöscht werden. Die Bestellung ist Teil des gekappten Sammlungsdesigns, das sicherstellt, dass die ältesten Dokumente zuerst "altern".

Stennie
quelle
4
Bedeutet dies also, dass ich unterschiedliche Ergebnisse erhalte, wenn ich denselben Suchbefehl ausführe: db.collection.find ({"x": y}). Skip (20000) .limit (1000) zu zwei verschiedenen Zeitpunkten setzt? Was passiert, wenn zwischen den beiden Befehlen keine Schreibvorgänge stattgefunden haben?
Saurabhj
6
@saurabhj: Einige Beispiele hinzugefügt, die die natürliche Ordnung beeinflussen. Wenn Dokumente verschoben / gelöscht wurden, erhalten Sie möglicherweise unterschiedliche Ergebnismengen. Wenn keine Dokumente eingefügt / aktualisiert / gelöscht wurden, sollten Sie das gleiche Ergebnis erhalten. Das Hinzufügen von Indizes wirkt sich nicht auf den Speicherort von Dokumenten auf der Festplatte aus.
Stennie
7
Sollte auch die Einschränkung hinzufügen, dass bei Verwendung der Replikation die natürliche Reihenfolge zwischen den Mitgliedern des Replikatsatzes variieren kann.
Stennie
Weiß jemand, wie man einen der 2 hier kommentierten Punkte erzwingt? Wir haben versucht, Dokumente zu ändern, aber sie werden immer noch in ihrer Einfügereihenfolge zurückgegeben ... Ich bin gespannt, ob sich die natürliche Reihenfolge von der Einfügereihenfolge unterscheiden kann.
Ferran Maylinch
Das Erzwingen einer Standardreihenfolge (z. B. {createdAt: -1}) ist erforderlich, um optimistische Benutzeroberflächenmuster zu implementieren (Aktualisieren von Datenlisten im Cache, ohne auf die Serverantwort nach einem Erstellen / Aktualisieren / Löschen zu warten). Andernfalls können Sie die clientseitige optimistische Reihenfolge und die Serverantwortreihenfolge nicht abgleichen.
Eric Burel
8

Es wird in der gespeicherten Reihenfolge (Reihenfolge in der Datei) zurückgegeben, es kann jedoch nicht garantiert werden, dass sie in der eingefügten Reihenfolge vorliegen. Sie sind nicht nach dem Feld _id sortiert. Manchmal kann es so aussehen, als wäre es nach der Einfügereihenfolge sortiert, aber es kann sich in einer anderen Anfrage ändern. Es ist nicht zuverlässig.

Parvin Gasimzade
quelle