6

マルチキーインデックスが定義されたドキュメントのコレクションがあります。ただし、クエリのパフォーマンスは、わずか43Kのドキュメントではかなり劣ります。このクエリの約215ミリ秒は不十分と見なされますか?nscannedが43902(コレクション内のドキュメントの総数に等しい)の場合、インデックスを正しく定義しましたか?

書類:

{
    "_id": {
        "$oid": "50f7c95b31e4920008dc75dc"
    },
    "bank_accounts": [
        {
            "bank_id": {
                "$oid": "50f7c95a31e4920009b5fc5d"
            },
            "account_id": [
                "ff39089358c1e7bcb880d093e70eafdd",
                "adaec507c755d6e6cf2984a5a897f1e2"
            ]
        }
    ],
    "created_date": "2013,01,17,09,50,19,274089",
}

索引:

{ "bank_accounts.bank_id" : 1 , "bank_accounts.account_id" : 1}

クエリ:

db.visitor.find({ "bank_accounts.account_id" : "ff39089358c1e7bcb880d093e70eafdd" , "bank_accounts.bank_id" : ObjectId("50f7c95a31e4920009b5fc5d")}).explain()

説明:

{
    "cursor" : "BtreeCursor bank_accounts.bank_id_1_bank_accounts.account_id_1",
    "isMultiKey" : true,
    "n" : 1,
    "nscannedObjects" : 43902,
    "nscanned" : 43902,
    "nscannedObjectsAllPlans" : 43902,
    "nscannedAllPlans" : 43902,
    "scanAndOrder" : false,
    "indexOnly" : false,
    "nYields" : 0,
    "nChunkSkips" : 0,
    "millis" : 213,
    "indexBounds" : {
        "bank_accounts.bank_id" : [
            [
                ObjectId("50f7c95a31e4920009b5fc5d"),
                ObjectId("50f7c95a31e4920009b5fc5d")
            ]
        ],
        "bank_accounts.account_id" : [
            [
                {
                    "$minElement" : 1
                },
                {
                    "$maxElement" : 1
                }
            ]
        ]
    },
    "server" : "Not_Important"
}
4

1 に答える 1

8

私は3つの要因が関係していると思います。

まず、アプリケーションの目的で、$elemMatchがこのユースケースにとってより適切なクエリではないことを確認してください。http://docs.mongodb.org/manual/reference/operator/elemMatch/。クエリを満たす複数のサブドキュメントが原因で間違った結果が返されたら、それは悪いことのようです。

次に、nscannedの高い値は、各フィールド値を個別にクエリすることで説明できると思います。.find({bank_accounts.bank_id:X})vs. .find({"bank_accounts.account_id":Y})。完全なクエリのnscannedは、最大のサブクエリのnscannedとほぼ同じであることがわかります。インデックスキーが範囲として完全に評価されている場合、これは予期されませんが...

第三に、ExplainPlanの{"bank_accounts.account_id":[[{"$ minElement":1}、{"$ maxElement":1}]]}句は、キーのこの部分に範囲が適用されていないことを示しています。

理由はよくわかりませんが、account_idの性質(配列内のサブドキュメント内の配列)と関係があるのではないかと思います。200msは、その高さのnscannedにはほぼ適切のようです。

よりパフォーマンスの高いドキュメント編成は、サブドキュメント内のaccount_id-> bank_id関係を非正規化し、以下を保存することです。

{"bank_accounts": [
{
 "bank_id": X,
 "account_id: Y,
},
{
 "bank_id": X,
 "account_id: Z,
}
]}

代わりに:{"bank_accounts":[{"bank_id":X、 "account_id:[Y、Z]、}]}

以下の私のテストは、この組織では、クエリオプティマイザーが動作を再開し、両方のキーに範囲を適用することを示しています。

> db.accounts.insert({"something": true, "blah": [{ a: "1", b: "2"} ] })
> db.accounts.ensureIndex({"blah.a": 1, "blah.b": 1})
> db.accounts.find({"blah.a": 1, "blah.b": "A RANGE"}).explain()
{
    "cursor" : "BtreeCursor blah.a_1_blah.b_1",
    "isMultiKey" : false,
    "n" : 0,
    "nscannedObjects" : 0,
    "nscanned" : 0,
    "nscannedObjectsAllPlans" : 0,
    "nscannedAllPlans" : 0,
    "scanAndOrder" : false,
    "indexOnly" : false,
    "nYields" : 0,
    "nChunkSkips" : 0,
    "millis" : 0,
    "indexBounds" : {
        "blah.a" : [
            [
                1,
                1
            ]
        ],
        "blah.b" : [
            [
                "A RANGE",
                "A RANGE"
        ]
    ]
    }
}
于 2013-02-19T21:52:18.863 に答える