为什么检查所有键的索引mongos查询具有排序和限制?

时间:2015-11-18 19:56:25

标签: mongodb

我有一个mongos设置,包含2个分片和以下数据:

for (var i = 1; i <= 1000; i++) { 
    db.items.insert({item: "a", i_type: "x", i_id: i, price: i * 50});
    db.items.insert({item: "a", i_type: "y", i_id: i, price: i * 50});
    db.items.insert({item: "b", i_type: "x", i_id: i, price: i * 50});
    db.items.insert({item: "b", i_type: "y", i_id: i, price: i * 50});
}
db.items.createIndex({item: 1, i_type: 1, i_id: 1}, {unique: true})
db.items.createIndex({item: 1, i_type: 1, price: 1})
sh.enableSharding("test")
sh.shardCollection("test.items", {item: 1, i_type: 1})

我跑了这个:

db.items.find(
    {item: "a", i_type: {$in: ["x", "y"]}},
    {_id: 0, item: 1, i_type: 1}
).sort({price: 1}).limit(10).explain("executionStats")

获取以下executionStats

"nReturned" : NumberInt(10), 
"executionTimeMillis" : NumberInt(22), 
"totalKeysExamined" : NumberInt(2000), 
"totalDocsExamined" : NumberInt(2000), 
"executionStages" : {
    "stage" : "SINGLE_SHARD", 
    "nReturned" : NumberInt(10), 
    "executionTimeMillis" : NumberInt(22), 
    "totalKeysExamined" : NumberInt(2000), 
    "totalDocsExamined" : NumberInt(2000), 
    "totalChildMillis" : NumberLong(21), 
    "shards" : [
        {
            "shardName" : "rs1", 
            "executionSuccess" : true, 
            "executionStages" : {
                "stage" : "PROJECTION", 
                "nReturned" : NumberInt(10), 
                "executionTimeMillisEstimate" : NumberInt(0), 
                "works" : NumberInt(2013), 
                "advanced" : NumberInt(10), 
                "needTime" : NumberInt(2002), 
                "needFetch" : NumberInt(0), 
                "saveState" : NumberInt(47), 
                "restoreState" : NumberInt(47), 
                "isEOF" : NumberInt(1), 
                "invalidates" : NumberInt(0), 
                "transformBy" : {
                    "_id" : NumberInt(0), 
                    "item" : NumberInt(1), 
                    "i_type" : NumberInt(1)
                }, 
                "inputStage" : {
                    "stage" : "SORT", 
                    "nReturned" : NumberInt(10), 
                    "executionTimeMillisEstimate" : NumberInt(0), 
                    "works" : NumberInt(2013), 
                    "advanced" : NumberInt(10), 
                    "needTime" : NumberInt(2001), 
                    "needFetch" : NumberInt(0), 
                    "saveState" : NumberInt(47), 
                    "restoreState" : NumberInt(47), 
                    "isEOF" : NumberInt(1), 
                    "invalidates" : NumberInt(0), 
                    "sortPattern" : {
                        "price" : NumberInt(1)
                    }, 
                    "memUsage" : NumberInt(850), 
                    "memLimit" : NumberInt(33554432), 
                    "limitAmount" : NumberInt(10), 
                    "inputStage" : {
                        "stage" : "FETCH", 
                        "nReturned" : NumberInt(2000), 
                        "executionTimeMillisEstimate" : NumberInt(0), 
                        "works" : NumberInt(2001), 
                        "advanced" : NumberInt(2000), 
                        "needTime" : NumberInt(0), 
                        "needFetch" : NumberInt(0), 
                        "saveState" : NumberInt(47), 
                        "restoreState" : NumberInt(47), 
                        "isEOF" : NumberInt(1), 
                        "invalidates" : NumberInt(0), 
                        "docsExamined" : NumberInt(2000), 
                        "alreadyHasObj" : NumberInt(0), 
                        "inputStage" : {
                            "stage" : "SHARDING_FILTER", 
                            "nReturned" : NumberInt(2000), 
                            "executionTimeMillisEstimate" : NumberInt(0), 
                            "works" : NumberInt(2001), 
                            "advanced" : NumberInt(2000), 
                            "needTime" : NumberInt(0), 
                            "needFetch" : NumberInt(0), 
                            "saveState" : NumberInt(47), 
                            "restoreState" : NumberInt(47), 
                            "isEOF" : NumberInt(1), 
                            "invalidates" : NumberInt(0), 
                            "chunkSkips" : NumberInt(0), 
                            "inputStage" : {
                                "stage" : "IXSCAN", 
                                "nReturned" : NumberInt(2000), 
                                "executionTimeMillisEstimate" : NumberInt(0), 
                                "works" : NumberInt(2001), 
                                "advanced" : NumberInt(2000), 
                                "needTime" : NumberInt(0), 
                                "needFetch" : NumberInt(0), 
                                "saveState" : NumberInt(47), 
                                "restoreState" : NumberInt(47), 
                                "isEOF" : NumberInt(1), 
                                "invalidates" : NumberInt(0), 
                                "keyPattern" : {
                                    "item" : NumberInt(1), 
                                    "i_type" : NumberInt(1), 
                                    "price" : NumberInt(1)
                                }, 
                                "indexName" : "item_1_i_type_1_price_1", 
                                "isMultiKey" : false, 
                                "direction" : "forward", 
                                "indexBounds" : {
                                    "item" : [
                                        "[\"a\", \"a\"]"
                                    ], 
                                    "i_type" : [
                                        "[\"x\", \"x\"]", 
                                        "[\"y\", \"y\"]"
                                    ], 
                                    "price" : [
                                        "[MinKey, MaxKey]"
                                    ]
                                }, 
                                "keysExamined" : NumberInt(2000), 
                                "dupsTested" : NumberInt(0), 
                                "dupsDropped" : NumberInt(0), 
                                "seenInvalidated" : NumberInt(0), 
                                "matchTested" : NumberInt(0)
                            }
                        }
                    }
                }
            }
        }
    ]
}

我很难理解为什么需要在分片上检查包含{item: "a", i_type: "x"}{item: "a", i_type: "y"}的所有密钥。该解释表明它正在使用适当的索引。

如果我在文档所在的副本集上运行相同的查询,则totalKeysExamined为10.如果我删除了mongos上单个i_type的排序或查询,totalKeysExamined是10(或11取决于自动平衡)。所有这些查询计划都有executionStage LIMIT,我在上面发布的解释中明显遗漏了executionStage

根据自动平衡器决定执行操作的方式,层次结构中的第一个SHARD_MERGE_SORT可能是SINGLE_SHARD而不是{{1}},但即使查询需要从两者获取信息碎片我认为只需要检查20个密钥(每个碎片10个)。

这是我遇到的mongos的限制,我需要改进选择的分片键和索引,还是完全不同的东西?

0 个答案:

没有答案