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

MongoDb:So erstellen Sie den richtigen (zusammengesetzten) Index für Daten mit vielen durchsuchbaren Feldern

Ich werde versuchen, anhand eines Beispiels zu erklären, was das bedeutet. Die auf B-Tree basierenden Indizes sind nichts Mongodb-spezifisches. Im Gegensatz dazu ist es ein eher gängiges Konzept.

Wenn Sie also einen Index erstellen, zeigen Sie der Datenbank einen einfacheren Weg, etwas zu finden. Aber dieser Index wird irgendwo mit einem Zeiger gespeichert, der auf eine Stelle des Originaldokuments zeigt. Diese Informationen sind geordnet und können als binärer Baum betrachtet werden, der eine wirklich nette Eigenschaft hat:Die Suche wird von O(n) reduziert (linearer Scan) zu O(log(n)) . Das ist viel, viel schneller, weil wir jedes Mal unseren Speicherplatz halbieren (möglicherweise können wir die Zeit von 10 ^ 6 auf 20 Suchen reduzieren). Zum Beispiel haben wir eine große Sammlung mit dem Feld {a : some int, b: 'some other things'} und wenn wir es mit a indizieren, erhalten wir eine andere Datenstruktur, die nach a sortiert ist . Es sieht so aus (damit meine ich nicht, dass es sich um eine weitere Sammlung handelt, dies dient nur der Demonstration):

{a : 1, pointer: to the field with a = 1}, // if a is the smallest number in the starting collection
...
{a : 999, pointer: to the field with a = 990} // assuming that 999 is the biggest field

Also suchen wir jetzt nach einem Feld a =18. Anstatt alle Elemente einzeln durchzugehen, nehmen wir etwas in der Mitte und wenn es größer als 18 ist, dann teilen wir den unteren Teil in zwei Hälften und prüfen das Element dort . Wir fahren fort, bis wir a =18 finden. Dann schauen wir uns den Zeiger an und da wir ihn kennen, extrahieren wir das ursprüngliche Feld.

Ähnlich verhält es sich mit zusammengesetzten Indizes (anstatt nach einem Element zu ordnen, ordnen wir nach vielen). Zum Beispiel haben Sie eine Sammlung:

{ "item": 5, "location": 1, "stock": 3, 'a lot of other fields' }  // was stored at position 5 on the disk
{ "item": 1, "location": 3, "stock": 1, 'a lot of other fields' }  // position 1 on the disk
{ "item": 2, "location": 5, "stock": 7, 'a lot of other fields' }  // position 3 on the disk
... huge amount of other data
{ "item": 1, "location": 1, "stock": 1, 'a lot of other fields' }  // position 9 on the disk
{ "item": 1, "location": 1, "stock": 2, 'a lot of other fields' }  // position 7 on the disk

und wollen einen Index { "item":1, "location":1, "stock":1 }. Die Nachschlagetabelle würde wie folgt aussehen (noch einmal - dies ist keine weitere Sammlung, dies dient nur der Demonstration):

{ "item": 1, "location": 1, "stock": 1, pointer = 9 }
{ "item": 1, "location": 1, "stock": 2, pointer = 7 }
{ "item": 1, "location": 3, "stock": 1, pointer = 1 }
{ "item": 2, "location": 5, "stock": 7, pointer = 3 }
.. huge amount of other data (but not necessarily here. If item would be one it would be somewhere next to items 1)
{ "item": 5, "location": 1, "stock": 3, pointer = 5 }

Beachten Sie, dass hier alles grundsätzlich nach Element, dann nach Ort und dann nach Zeiger sortiert ist. Genauso wie bei einem einzelnen Index müssen wir nicht alles scannen. Wenn wir eine Abfrage haben, die nach item = 2, location = 5 and stock = 7 sucht Wir können schnell erkennen, wo Dokumente mit item = 2 sind sind und dann auf die gleiche Weise schnell feststellen, wo sich unter diesen Artikeln Artikel mit location 5 befinden und so weiter.

Und gerade jetzt ein interessanter Teil . Außerdem haben wir nur einen Index erstellt (obwohl dies ein zusammengesetzter Index ist, ist es immer noch ein Index), den wir verwenden können, um das Element

schnell zu finden
  • nur nach dem item . Wirklich alles, was wir tun müssen, ist nur der erste Schritt. Es macht also keinen Sinn, einen weiteren Index {location :1} zu erstellen, da dieser bereits durch einen zusammengesetzten Index abgedeckt ist.
  • auch können wir schnell nur nach item and by location finden (wir brauchen nur 2 Schritte).

Cool 1 Index hilft uns aber auf drei verschiedene Arten. Aber Moment mal:Was ist, wenn wir nach item and stock suchen wollen? . Oh, es sieht so aus, als könnten wir diese Abfrage auch beschleunigen. Wir können in log(n) alle Elemente mit bestimmten Items finden und ... hier müssen wir aufhören - die Magie ist beendet. Wir müssen sie alle durchlaufen. Aber immer noch ziemlich gut.

Aber vielleicht hilft es uns bei anderen Fragen. Sehen wir uns eine Abfrage nach location an das sieht aus wie schon bestellt. Aber wenn Sie es sich ansehen, sehen Sie, dass dies ein Durcheinander ist. Eine am Anfang und dann eine am Ende. Es kann dir überhaupt nicht helfen.

Ich hoffe, das verdeutlicht einige Dinge:

  • Warum Indizes gut sind (Reduzierung der Zeit von O(n) auf möglicherweise O(log(n))
  • Warum zusammengesetzte Indizes bei einigen Abfragen helfen können, haben wir dennoch keinen Index für dieses bestimmte Feld erstellt und helfen bei einigen anderen Abfragen.
  • welche Indizes werden durch zusammengesetzte Indizes abgedeckt
  • warum Indizes schaden können (sie schaffen zusätzliche Datenstrukturen, die gepflegt werden sollten)

Und dies sollte eine andere gültige Sache sagen:Index ist keine Wunderwaffe . Sie können nicht alle Ihre Abfragen beschleunigen, daher klingt es albern zu glauben, dass durch das Erstellen von Indizes für alle Felder ALLES superschnell wäre.