6

3,500 万post個のオブジェクトで名前が付けられた MongoDB コレクションがあります。コレクションには、次のように定義された 2 つのセカンダリ インデックスがあります。

> db.post.getIndexKeys()
[
    {
        "_id" : 1
    },
    {
        "namespace" : 1,
        "domain" : 1,
        "post_id" : 1
    },
    {
        "namespace" : 1,
        "post_time" : 1,
        "tags" : 1  // this is an array field
    }
]

と で単純にフィルタリングする次のクエリは、すべてのオブジェクトをスキャンせずに妥当な時間内に実行されるnamespaceと思います。post_time

>db.post.find({post_time: {"$gte" : ISODate("2013-04-09T00:00:00Z"), "$lt" : ISODate("2013-04-09T01:00:00Z")}, namespace: "my_namespace"}).count()
7408

ただし、MongoDB が結果を取得するには少なくとも 10 分かかり、興味深いことに、MongoDBは関数に従ってジョブを実行するために7,000 万explainのオブジェクトをスキャンすることに成功しています。

> db.post.find({post_time: {"$gte" : ISODate("2013-04-09T00:00:00Z"), "$lt" : ISODate("2013-04-09T01:00:00Z")}, namespace: "my_namespace"}).explain()
{
    "cursor" : "BtreeCursor namespace_1_post_time_1_tags_1",
    "isMultiKey" : true,
    "n" : 7408,
    "nscannedObjects" : 69999186,
    "nscanned" : 69999186,
    "nscannedObjectsAllPlans" : 69999186,
    "nscannedAllPlans" : 69999186,
    "scanAndOrder" : false,
    "indexOnly" : false,
    "nYields" : 378967,
    "nChunkSkips" : 0,
    "millis" : 290048,
    "indexBounds" : {
        "namespace" : [
            [
                "my_namespace",
                "my_namespace"
            ]
        ],
        "post_time" : [
            [
                ISODate("2013-04-09T00:00:00Z"),
                ISODate("292278995-01--2147483647T07:12:56.808Z")
            ]
        ],
        "tags" : [
            [
                {
                    "$minElement" : 1
                },
                {
                    "$maxElement" : 1
                }
            ]
        ]
    },
    "server" : "localhost:27017"
}

オブジェクトの数とスキャンの数の違いは、タグ配列の長さ (すべて 2 に等しい) によって発生する必要があります。post_timeそれでも、フィルターがインデックスを利用しない理由がわかりません。

何が欠けているのか教えてもらえますか?

(私は 24 コアと 96 GB RAM の降下マシンで作業しています。MongoDB 2.2.3 を使用しています。)

4

1 に答える 1