MongoDB Multikey Compound Index - Brauche Hilfe zum Verständnis von Grenzen

Wir haben vor kurzem beschlossen, einige unserer MongoDB-Indizes erneut zu besuchen, und sind bei der Verwendung eines zusammengesetzten Indexes, der einen Teil mit mehreren Schlüsseln enthält, auf ein besonderes Ergebnis gestoßen.

Es ist wichtig zu beachten, dass wir v2.4.5 verwenden

TLDR: Wenn Sie einen zusammengesetzten Index mit mehrtastigem Teil verwenden,die Grenzen eines Non-Multikey Das Feld für die Bereichsbeschränkung wird gelöscht.

Ich erkläre das Problem anhand eines Beispiels:

Erstellen Sie einige Daten

db.demo.insert(
[{ "foo" : 1, "attr" : [  {  "name" : "a" },  {  "name" : "b" },  {  "name" : "c" } ]},
 { "foo" : 2, "attr" : [  {  "name" : "b" },  {  "name" : "c" },  {  "name" : "d" } ]},
 { "foo" : 3, "attr" : [  {  "name" : "c" },  {  "name" : "d" },  {  "name" : "e" } ]},
 { "foo" : 4, "attr" : [  {  "name" : "d" },  {  "name" : "e" },  {  "name" : "f" } ]}])

Index

db.demo.ensureIndex({'attr.name': 1, 'foo': 1})

Fragen & Erklären

Fragen Sie nach 'attr.name', beschränken Sie jedoch den Bereich des Nicht-Multikey-Felds 'foo':

db.demo.find({foo: {$lt:3, $gt: 1}, 'attr.name': 'c'}).hint('attr.name_1_foo_1').explain()
{
    "cursor" : "BtreeCursor attr.name_1_foo_1",
    "isMultiKey" : true,
    "n" : 1,
    "nscannedObjects" : 2,
    "nscanned" : 2,
    "nscannedObjectsAllPlans" : 2,
    "nscannedAllPlans" : 2,
    "scanAndOrder" : false,
    "indexOnly" : false,
    "nYields" : 0,
    "nChunkSkips" : 0,
    "millis" : 0,
    "indexBounds" : {
        "attr.name" : [
            [
                "c",
                "c"
            ]
        ],
        "foo" : [
            [
                -1.7976931348623157e+308,
                3
            ]
        ]
    }
}

Wie Sie sehen, entspricht der Bereich von 'foo' nicht der Definition in der Abfrage. Ein Ende wird vollständig ignoriert, was dazu führt, dass nscanned größer ist als es sollte.

Durch Ändern der Reihenfolge der Bereichsoperanden wird das abgelegte Ende geändert:

db.demo.find({foo: {$gt: 1, $lt:3}, 'attr.name': 'c'}).hint('attr.name_1_foo_1').explain()
{
    "cursor" : "BtreeCursor attr.name_1_foo_1",
    "isMultiKey" : true,
    "n" : 1,
    "nscannedObjects" : 2,
    "nscanned" : 2,
    "nscannedObjectsAllPlans" : 2,
    "nscannedAllPlans" : 2,
    "scanAndOrder" : false,
    "indexOnly" : false,
    "nYields" : 0,
    "nChunkSkips" : 0,
    "millis" : 0,
    "indexBounds" : {
        "attr.name" : [
            [
                "c",
                "c"
            ]
        ],
        "foo" : [
            [
                1,
                1.7976931348623157e+308
            ]
        ]
    }
}

Entweder verpassen wir einige Grundlagen für Multikey-Indizes, oder wir haben einen Fehler.

Wir haben ähnliche Themen behandelt, darunter:

https://groups.google.com/forum/#!searchin/mongodb-user/multikey$20bounds/mongodb-user/RKrsyzRwHrE/_i0SxdJV5qcJReihenfolge von $ lt und $ gt in der Abfrage des MongoDB-Bereichs

Leider sprechen diese Beiträge einen anderen Anwendungsfall an, bei dem ein Bereich auf den Wert für mehrere Schlüssel festgelegt wird.

Andere Dinge, die wir versucht haben:

Ändern Sie die Reihenfolge der zusammengesetzten Indizes, indem Sie mit dem Nicht-Mehrfachschlüssel-Feld beginnen.

Setzen Sie den 'foo'-Wert in jedes der Filialdokumente im' attr'-Array, indexieren Sie nach ('attr.name', 'attr.foo') und führen Sie einen $ elemMatch für 'attr' mit einer Bereichsbeschränkung für 'foo' durch. .

Verwenden Sie beim Definieren des Bereichs einen $ und -Operator:

db.demo.find({'attr.name': 'c', $and: [{num: {$lt: 3}}, {num: {$gt: 1}}]})

Verwenden Sie MongoDB v2.5.4

Keiner der oben genannten Punkte hatte irgendeine Auswirkung (v2.5.4 verschlimmerte die Situation, indem beide Enden des Bereichs vollständig gelöscht wurden).

Jede Art von Hilfe wäre sehr dankbar!

Danke vielmals,

Roi

Antworten auf die Frage(2)

Ihre Antwort auf die Frage