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

MongoDB Multikey-Indizes und Index-Schnittgrenzen

MongoDB bietet hervorragende Unterstützung für Arrays und bietet viel Flexibilität in Ihrem Dokumentmodus. Sie können beispielsweise Arrays in Dokumente einbetten und auch Dokumente in Arrays einbetten usw. Die Arbeit mit Arrays hat jedoch eine Reihe von Fallstricken in MongoDB. In diesem Beitrag sehen wir uns einige der Probleme an, die MongoDB mit Indizes und Arrays hat.

Multikey-Indizes

In MongoDB können Sie ein Arrayfeld indizieren, um einen Indexeintrag für jedes Element im Array zu erstellen. Der resultierende Index wird als „Multikey“-Index bezeichnet. Multikey-Indizes können über Skalarwerte oder eingebettete Dokumente erstellt werden. Weitere Informationen zu Multikey-Indexen finden Sie in dieser Dokumentation.

Multikey-Indizes sind zwar nützlich, haben aber mehrere Einschränkungen:

  • Wenn Sie einen zusammengesetzten Multikey-Index erstellen, haben Sie höchstens ein Feld, das ein Array ist.
  • Ein zusammengesetzter Index kann kein Shard-Schlüssel sein.
  • Ein zusammengesetzter Index kann kein Hash-Index sein.
MongoDB-Multikey-Indexbeschränkungen – Worauf Sie bei Ihren Abfragen achten solltenClick To Tweet

Einer der interessantesten Aspekte von Multikey-Indizes ist, wie Index-Schnittpunktgrenzen berechnet werden.

Indexschnittgrenzen

So definiert die MongoDB-Dokumentation Index-Schnittgrenzen:

„Die Grenzen eines Index-Scans definieren die Teile eines Index, die während einer Abfrage durchsucht werden sollen. Wenn mehrere Prädikate für einen Index vorhanden sind, versucht MongoDB, die Grenzen für diese Prädikate entweder durch Schnittmenge zu kombinieren oder Verbindung um einen Scan mit kleineren Grenzen zu erzeugen.“

Bereichsabfragen auf Arrays

Beginnen wir mit einem einfachen Beispiel, um zu sehen, wie MongoDB Indexgrenzen für Abfragen auf Arrays berechnet. Angenommen, wir haben die folgenden drei Dokumente in einer Sammlung:

{x:65}{x:35}{x:[12,95]}

Wir geben die folgende Abfrage aus:

db.coll.find({x :{ $gt :22, $lt:55})

Die Abfrage ist einfach genug. Sie würden erwarten, dass die Antwort {x:35} lautet, aber die Abfrage gibt zurück:

{x:35}{x:[25,95]}

Der Grund liegt darin, wie MongoDB mit Arrays umgeht. Dasselbe Element des Arrays muss nicht mit beiden Bedingungen übereinstimmen; Solange es ein Element gibt, das jeder Bedingung entspricht, ist es eine Übereinstimmung. In diesem Fall sind die Grenzen also [22, Infinity] und [-Infinity, 55]. Da kein „elemMatch“-Operator verwendet wird, verwendet MongoDB die Index-Schnittmenge nicht. MongoDB gibt nicht an, welcher dieser Bereiche [22, Infinity] oder [-Infinity, 55] für die Ausführung der Abfrage verwendet wird.

Wenn wir die Index-Schnittmenge verwenden möchten, müssen wir die folgende Abfrage verwenden:

db.coll.find(x :{ $elemMatch:{$gt :22,$lt:55}})

Wenn Sie dies verwenden, schneidet MongoDB die Indexgrenzen und verwendet [22, 55] als Grenzen. Wie erwartet gibt diese Abfrage keine Ergebnisse zurück (elemMatch stimmt nicht mit Nicht-Arrays überein). Daher sind Bereichsabfragen auf Arrays ohne den $elemMatch-Operator ziemlich nutzlos.

Zusammengesetzte Multikey-Indizes – Mischen von Array- und Nicht-Array-Feldern

Betrachten Sie eine Sammlung mit den folgenden Dokumenten:

{Artikel:35, Preise:[250,35]}......{Artikel:106, Preise:[1500,65]}

Wir fügen dieser Sammlung einen zusammengesetzten Index hinzu:

db.ensureIndex({item:1, price:1});

Lassen Sie uns nun eine einfache Abfrage ausführen:

db. coll. find({item:{$gt:12, $lt:65}});

Die Abfrage sieht einfach genug aus, da wir ein Nicht-Array-Element mit einem festen Bereich verwenden. Ich erwarte, dass die Schnittpunktgrenzen des Index so etwas wie item:[[12,65] ] für die Abfrage sind, aber wenn Sie ein Explain ausführen, sehen Sie Folgendes:

"indexBounds" :{"item" :[ [ -Infinity, 65 ] ],"prices" :[ [ { "$minElement" :1 }, { "$maxElement" :1 } ] ]}, 

Der Grund dafür ist, dass MongoDB erkennt, dass es sich um einen Multikey-Index handelt, und die Überschneidung der Indexgrenzen nicht verarbeitet, unabhängig davon, dass Ihre Abfrage keine Array-Felder verwendet. Die Moral von der Geschichte lautet:Wenn Sie Array- und Nicht-Array-Felder in einem Index mischen, behalten Sie immer die Index-Schnittpunktgrenzen im Auge. Die Chancen stehen gut, dass es nicht effizient ist.