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

Zusammengesetzte MongoDB-Indizes – Spielt die Sortierreihenfolge eine Rolle?

Sie können sich den Einzelfeldindex von MongoDB als ein Array mit Zeigern auf Dokumentspeicherorte vorstellen. Wenn Sie beispielsweise eine Sammlung haben mit (beachten Sie, dass die Reihenfolge absichtlich falsch ist):

[collection]
1: {a:3, b:2}
2: {a:1, b:2}
3: {a:2, b:1}
4: {a:1, b:1}
5: {a:2, b:2}

Einzelfeldindex

Wenn Sie das jetzt tun:

db.collection.createIndex({a:1})

Der Index sieht ungefähr so ​​aus:

[index a:1]
1: {a:1} --> 2, 4
2: {a:2} --> 3, 5
3: {a:3} --> 1

Beachten Sie drei wichtige Dinge:

  • Es ist nach a sortiert aufsteigend
  • Jeder Eintrag verweist auf den Ort, an dem sich die relevanten Dokumente befinden
  • Der Index zeichnet nur die Werte des a auf aufstellen. Das b Feld existiert überhaupt nicht im Index

Wenn Sie also eine Abfrage wie:

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

Alles, was es tun muss, ist, den Index von oben nach unten zu durchlaufen und das Dokument, auf das die Einträge verweisen, abzurufen und auszugeben. Beachten Sie, dass Sie den Index auch von unten durchlaufen können, z. B.:

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

und der einzige Unterschied besteht darin, dass Sie den Index rückwärts durchlaufen.

Weil b überhaupt nicht im Index enthalten ist, können Sie den Index nicht verwenden, wenn Sie irgendetwas über b abfragen .

Verbindungsindex

In einem zusammengesetzten Index z. B.:

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

Das bedeutet, dass Sie nach a sortieren möchten zuerst, dann nach b sortieren . Der Index würde folgendermaßen aussehen:

[index a:1, b:1]
1: {a:1, b:1} --> 4
2: {a:1, b:2} --> 2
3: {a:2, b:1} --> 3
4: {a:2, b:2} --> 5
5: {a:3, b:2} --> 1

Beachten Sie Folgendes:

  • Der Index wird ab a sortiert
  • In jedem a Sie haben ein sortiertes b
  • Sie haben 5 Indexeinträge im Gegensatz zu nur drei im vorherigen Einzelfeldbeispiel

Mit diesem Index können Sie eine Abfrage wie die folgende durchführen:

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

Es kann leicht finden, wo a:2 Gehen Sie dann den Index vorwärts. Bei diesem Index geht das nicht :

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

In beiden Abfragen können Sie b nicht leicht finden da es über den gesamten Index verteilt ist (d. h. nicht in zusammenhängenden Einträgen). Wie auch immer Sie können tun:

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

da findet man im wesentlichen wo der a:2 sind, und gehen Sie den b Einträge rückwärts.

Bearbeiten :Klärung der Frage von @marcospgp im Kommentar:

Die Möglichkeit, den Index {a:1, b:1} zu verwenden um find({a:2}).sort({b:-1}) zu erfüllen eigentlich sinnvoll, wenn man es von einer sortierten Tabelle aus betrachtet. Zum Beispiel der Index {a:1, b:1} kann man sich vorstellen als:

a | b
--|--
1 | 1
1 | 2
2 | 1
2 | 2
2 | 3
3 | 1
3 | 2

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

Der Index {a:1, b:1} bedeutet sort by a, then within each a, sort the b values . Wenn Sie dann ein find({a:2}).sort({b:1}) machen , der Index weiß, wo alle a=2 sind sind. Innerhalb dieses Blocks von a=2 , das b aufsteigend sortiert werden (gemäß der Indexspezifikation), sodass die Abfrage find({a:2}).sort({b:1}) lautet kann erfüllt werden durch:

a | b
--|--
1 | 1
1 | 2
2 | 1 <-- walk this block forward to satisfy
2 | 2 <-- find({a:2}).sort({b:1})
2 | 3 <--
3 | 1
3 | 2

find({a:2}).sort({b:-1})

Da der Index vorwärts oder rückwärts gehen kann, wurde ein ähnliches Verfahren befolgt, mit einer kleinen Wendung am Ende:

a | b
--|--
1 | 1
1 | 2
2 | 1  <-- walk this block backward to satisfy
2 | 2  <-- find({a:2}).sort({b:-1})
2 | 3  <--
3 | 1
3 | 2

Die Tatsache, dass der Index vorwärts oder rückwärts durchlaufen werden kann, ist der entscheidende Punkt, der die Abfrage find({a:2}).sort({b:-1}) ermöglicht um den Index {a:1, b:1} verwenden zu können .

Abfrageplaner erklären

Sie können sehen, was der Abfrageplaner plant, indem Sie db.collection.explain().find(....) verwenden . Grundsätzlich, wenn Sie eine stage sehen von COLLSCAN , kein Index verwendet wurde oder für die Abfrage verwendet werden kann. Siehe Ergebnisse erklären für Details zur Ausgabe des Befehls.