LoginSignup
0
1

More than 5 years have passed since last update.

MongoDBのindexの使われ方

Posted at

コレクションにフィールド a, b, c があるとして、{ a: 1, b: 1, c: 1 }{ a: 1 }, { b: 1 }, { c: 1 } というindexがある場合...

> db.c1.getIndexes();
[
    {
        "v" : 1,
        "key" : {
            "_id" : 1
        },
        "name" : "_id_",
        "ns" : "test.c1"
    },
    {
        "v" : 1,
        "key" : {
            "a" : 1,
            "b" : 1,
            "c" : 1
        },
        "name" : "a_1_b_1_c_1",
        "ns" : "test.c1"
    },
    {
        "v" : 1,
        "key" : {
            "a" : 1
        },
        "name" : "a_1",
        "ns" : "test.c1"
    },
    {
        "v" : 1,
        "key" : {
            "b" : 1
        },
        "name" : "b_1",
        "ns" : "test.c1"
    },
    {
        "v" : 1,
        "key" : {
            "c" : 1
        },
        "name" : "c_1",
        "ns" : "test.c1"
    }
]

いろんなパターンで試してみる

find( { a: 1 } ) した場合

> db.c1.find( { a: 1 } ).explain();
{
    "cursor" : "BtreeCursor a_1_b_1_c_1",
    "isMultiKey" : false,
    "n" : 1,
    "nscannedObjects" : 1,
    "nscanned" : 1,
    "nscannedObjectsAllPlans" : 2,
    "nscannedAllPlans" : 2,
    "scanAndOrder" : false,
    "indexOnly" : false,
    "nYields" : 0,
    "nChunkSkips" : 0,
    "millis" : 10,
    "indexBounds" : {
        "a" : [
            [
                1,
                1
            ]
        ],
        "b" : [
            [
                {
                    "$minElement" : 1
                },
                {
                    "$maxElement" : 1
                }
            ]
        ],
        "c" : [
            [
                {
                    "$minElement" : 1
                },
                {
                    "$maxElement" : 1
                }
            ]
        ]
    },
    "server" : "pellinore.local:27017",
    "filterSet" : false
}

{ a: 1, b: 1, c: 1 }が使われました。

あ、{ a: 1 }じゃなくてそっちなんですね。

find( { b: 1 } ) した場合

> db.c1.find( { b: 1 } ).explain();
{
    "cursor" : "BtreeCursor b_1",
    "isMultiKey" : false,
    "n" : 1,
    "nscannedObjects" : 1,
    "nscanned" : 1,
    "nscannedObjectsAllPlans" : 1,
    "nscannedAllPlans" : 1,
    "scanAndOrder" : false,
    "indexOnly" : false,
    "nYields" : 0,
    "nChunkSkips" : 0,
    "millis" : 0,
    "indexBounds" : {
        "b" : [
            [
                1,
                1
            ]
        ]
    },
    "server" : "pellinore.local:27017",
    "filterSet" : false
}

{ b: 1 }が使われました。
そんな気がしていました。

find( { a: 1, b: 1 } ) した場合

> db.c1.find( { a: 1, b: 1 } ).explain();
{
    "cursor" : "BtreeCursor b_1",
    "isMultiKey" : false,
    "n" : 1,
    "nscannedObjects" : 1,
    "nscanned" : 1,
    "nscannedObjectsAllPlans" : 3,
    "nscannedAllPlans" : 3,
    "scanAndOrder" : false,
    "indexOnly" : false,
    "nYields" : 0,
    "nChunkSkips" : 0,
    "millis" : 0,
    "indexBounds" : {
        "b" : [
            [
                1,
                1
            ]
        ]
    },
    "server" : "pellinore.local:27017",
    "filterSet" : false
}

{ b: 1 }が使われました。
{ a: 1, b: 1, c: 1 }を使うのかと思っていました。

find( { b: 1, a: 1 } ) した場合

{ b: 1 }が使われました。

find( { a: 1, c: 1 } ) した場合

{ c: 1 }が使われました。

find( { b: 1, c: 1 } ) した場合

{ c: 1 }が使われました。
ぴったり一致するのがないので{ b: 1 }{ c: 1 }のどちらかなんでしょう。

find( { a: 1, b: 1, c: 1 } ) した場合

{ c: 1 }が使われました。
な、なぜ!?

find( { a: 1, c: 1, b: 1 } ) した場合

{ c: 1 }が使われました。
う、うーん、、、

find( { a: 1, b: 1 } ).sort( { c: 1 } ) した場合

{ a: 1, b: 1, c: 1 }が使われました。

find( { b: 1, c: 1 } ).sort( { a: 1 } ) した場合

{ a: 1, b: 1, c: 1 }が使われました。

まとめ

  • { a: 1 }は一度も使われていないところを見ると、{ a: 1 }より{ a: 1, b: 1, c: 1 }のほうが優先されるみたい。
  • { a: 1, b: 1, c: 1 }のようにぴったり一致するindexがあっても使ってくれない場合があるみたい。

ちょっとよくわからないので、ドキュメントを読んでから追記予定。

参考

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1