MongoDB
 sql >> Datenbank >  >> NoSQL >> MongoDB

Wie funktioniert das Sortieren mit einem Index in MongoDB?

Indizes in MongoDB werden in einer B-Baumstruktur gespeichert, wobei jeder Indexeintrag auf einen bestimmten Speicherort auf der Festplatte verweist. Die Verwendung einer B-Tree-Struktur bedeutet auch, dass ein MongoDB-Index in einer sortierten Reihenfolge gespeichert und immer der Reihe nach durchlaufen wird, und es für MongoDB günstig ist, eine Reihe von Dokumenten in einer sortierten Reihenfolge über Indizes abzurufen.

Aktualisieren :Die B-Tree-Struktur gilt für die MMAPv1-Speicher-Engine, wird aber von der WiredTiger-Speicher-Engine etwas anders implementiert (Standard seit MongoDB 3.2). Die Grundidee bleibt die gleiche, wobei es billig ist, den Index in einer sortierten Reihenfolge zu durchlaufen.

Ein SORT Phase (d. h. In-Memory-Sortierung) in einer Abfrage ist auf 32 MB Speichernutzung begrenzt. Eine Abfrage schlägt fehl, wenn SORT Stufe überschreitet diese Grenze. Dieses Limit kann umgangen werden, indem die sortierte Natur von Indizes genutzt wird, sodass MongoDB eine Abfrage mit einem sort() zurückgeben kann -Parameter ohne Durchführung einer In-Memory-Sortierung.

Nehmen wir an, die Abfrage hat folgende Form:

    db.a.find({b:{$gt:100}, c:{$gt:200}}).sort(...)

mit Sammlung a mit einem Index von:

    db.a.createIndex({b:1,c:1})

Es gibt zwei mögliche Szenarien, wenn ein sort() Stufe wird in der Abfrage angegeben:

1. MongoDB kann die sortierte Natur des Indexes nicht verwenden und muss ein In-Memory-SORT durchführen Stufe .

Dies ist das Ergebnis, wenn die Abfrage das "Index-Präfix" nicht verwenden kann. Zum Beispiel:

    db.a.find({b:{$gt:100}, c:{$gt:200}}).sort({c:1})

In der obigen Abfrage ist der Index {b:1,c:1} kann verwendet werden für:

  • Passen Sie Dokumente mit b an größer als 100 für {b:{$gt:100}} Teil der Abfrage.
  • Es gibt jedoch keine Garantie, dass die zurückgesendeten Dokumente nach c sortiert sind .

Daher hat MongoDB keine andere Wahl, als eine In-Memory-Sortierung durchzuführen. Das explain() Die Ausgabe dieser Abfrage hat einen SORT Bühne. Dieses SORT stage auf 32 MB Speichernutzung begrenzt wäre.

2. MongoDB kann die sortierte Natur des Index verwenden .

Dies ist das Ergebnis, wenn die Abfrage Folgendes verwendet:

  • Schlüssel sortieren, die der Reihenfolge des Index entsprechen, und
  • Gibt dieselbe Reihenfolge wie der Index an (d. h. der Index {b:1,c:1} kann für sort({b:1,c:1}) verwendet werden oder sort({b:-1,c:-1}) aber nicht sort({b:1,c:-1}) )

Zum Beispiel:

    db.a.find({b:{$gt:100}, c:{$gt:200}}).sort({b:1})

In der obigen Abfrage ist der Index {b:1,c:1} kann verwendet werden für:

  • Passen Sie Dokumente mit b an größer als 100 für {b:{$gt:100}} Teil der Abfrage.
  • In diesem Fall kann MongoDB garantieren, dass die zurückgegebenen Dokumente nach b sortiert sind .

Das explain() Die Ausgabe der obigen Abfrage wird nicht einen SORT haben Bühne. Auch das explain() Ausgabe der Abfrage mit und ohne sort() sind identisch . Im Wesentlichen erhalten wir den sort() kostenlos.

Eine wertvolle Ressource zum Verständnis dieses Themas ist Optimizing MongoDB Compound Indexes. Bitte beachten Sie, dass dieser Blog-Beitrag bereits im Jahr 2012 geschrieben wurde. Auch wenn einige der Terminologie veraltet sein mögen, ist die technische Bedeutung des Beitrags immer noch relevant.

Update zu Folgefragen

  1. MongoDB verwendet für die meisten Abfragen nur einen Index. Also zum Beispiel um ein In-Memory SORT zu vermeiden Stufe in der Abfrage

    db.a.find({a:1}).sort({b:1})
    

    der Index muss sowohl a umfassen und b Felder gleichzeitig; z.B. ein zusammengesetzter Index wie {a:1,b:1} erforderlich. Sie können nicht zwei separate Indizes {a:1} haben und {b:1} , und erwarten Sie den {a:1} Index, der für den Gleichheitsteil verwendet werden soll, und {b:1} Index, der für den Sortierteil verwendet werden soll. In diesem Fall wählt MongoDB einen der beiden Indizes aus.

    Daher ist es richtig, dass die Ergebnisse sortiert werden, da sie in der Reihenfolge des Index gesucht und zurückgegeben werden.

  2. Um eine In-Memory-Sortierung mit einem zusammengesetzten Index zu vermeiden, muss der erste Teil des Index den Gleichheitsteil berücksichtigen der Abfrage, und der zweite Teil muss den Sortierteil bedienen der Abfrage (wie in der Erläuterung zu (1) oben gezeigt).

    Wenn Sie eine Abfrage wie diese haben:

    db.a.find({}).sort({a:1})
    

    der Index {a:1,b:1} kann für den Sortierteil verwendet werden (da Sie im Grunde die gesamte Sammlung zurückgeben). Und wenn Ihre Abfrage so aussieht:

    db.a.find({a:1}).sort({b:1})
    

    denselben Index {a:1,b:1} kann auch für beide Teile der Abfrage verwendet werden. Auch:

    db.a.find({a:1,b:1})
    

    kann auch denselben Index {a:1,b:1} verwenden

    Beachten Sie das Muster hier:find() gefolgt von sort() Parameter folgen der Indexreihenfolge {a:1,b:1} . Daher muss ein zusammengesetzter Index nach Gleichheit -> Sortierung geordnet werden .

Update zur Sortierung verschiedener Typen

Wenn ein Feld zwischen Dokumenten unterschiedliche Typen hat (z. B. wenn a ist String in einem Dokument, Zahl in anderen, Boolean in einem anderen), wie geht die Sortierung vor sich?

Die Antwort ist die MongoDB-BSON-Vergleichsreihenfolge. Um die Handbuchseite zu paraphrasieren, lautet die Reihenfolge:

  1. MinKey (interner Typ)
  2. Null
  3. Zahlen (ints, longs, doubles, decimals)
  4. Symbol, Zeichenfolge
  5. Objekt
  6. Array
  7. BinData
  8. Objekt-ID
  9. Boolean
  10. Datum
  11. Zeitstempel
  12. Regulärer Ausdruck
  13. MaxKey (interner Typ)

Aus dem obigen Beispiel mit aufsteigender Reihenfolge werden also zuerst Dokumente angezeigt, die Zahlen enthalten, dann Zeichenfolgen und dann boolesche Werte.