我有一个数据库,其中将一些文件放在GridFS中。这只是为了证明我要查询的fs.chunks集合。
我在这个集合中有20万块。我有以下索引_id
,n
和files_id_1_n_1
。
如果我运行聚合
db.fs.chunks.explain("executionStats").aggregate([{$sort: {n:-1}},{$match:{n:{$lt:100000}}}, {$skip:10000}, {$limit:70}, {$project: {_id:0, n:1}}])
。在这种情况下,所有投影的字段都会被索引。
要总结输出结果,我得到了"executionTimeMillis" : 32
,"totalKeysExamined" : 10070
和"totalDocsExamined" : 0
,这与我的想法完全一样。
如有必要,请在此处完整输出:
{
"stages" : [
{
"$cursor" : {
"query" : {
"n" : {
"$lt" : 100000
}
},
"sort" : {
"n" : -1
},
"limit" : NumberLong(10070),
"fields" : {
"n" : 1,
"_id" : 0
},
"queryPlanner" : {
"plannerVersion" : 1,
"namespace" : "OfflineAnalysisTool.fs.chunks",
"indexFilterSet" : false,
"parsedQuery" : {
"n" : {
"$lt" : 100000
}
},
"winningPlan" : {
"stage" : "PROJECTION",
"transformBy" : {
"n" : 1,
"_id" : 0
},
"inputStage" : {
"stage" : "IXSCAN",
"keyPattern" : {
"n" : 1
},
"indexName" : "files_id",
"isMultiKey" : false,
"multiKeyPaths" : {
"n" : [ ]
},
"isUnique" : false,
"isSparse" : false,
"isPartial" : false,
"indexVersion" : 2,
"direction" : "backward",
"indexBounds" : {
"n" : [
"(100000.0, -inf.0]"
]
}
}
},
"rejectedPlans" : [ ]
},
"executionStats" : {
"executionSuccess" : true,
"nReturned" : 10070,
"executionTimeMillis" : 32,
"totalKeysExamined" : 10070,
"totalDocsExamined" : 0,
"executionStages" : {
"stage" : "PROJECTION",
"nReturned" : 10070,
"executionTimeMillisEstimate" : 30,
"works" : 10070,
"advanced" : 10070,
"needTime" : 0,
"needYield" : 0,
"saveState" : 79,
"restoreState" : 79,
"isEOF" : 0,
"invalidates" : 0,
"transformBy" : {
"n" : 1,
"_id" : 0
},
"inputStage" : {
"stage" : "IXSCAN",
"nReturned" : 10070,
"executionTimeMillisEstimate" : 20,
"works" : 10070,
"advanced" : 10070,
"needTime" : 0,
"needYield" : 0,
"saveState" : 79,
"restoreState" : 79,
"isEOF" : 0,
"invalidates" : 0,
"keyPattern" : {
"n" : 1
},
"indexName" : "files_id",
"isMultiKey" : false,
"multiKeyPaths" : {
"n" : [ ]
},
"isUnique" : false,
"isSparse" : false,
"isPartial" : false,
"indexVersion" : 2,
"direction" : "backward",
"indexBounds" : {
"n" : [
"(100000.0, -inf.0]"
]
},
"keysExamined" : 10070,
"seeks" : 1,
"dupsTested" : 0,
"dupsDropped" : 0,
"seenInvalidated" : 0
}
}
}
}
},
{
"$skip" : NumberLong(10000)
},
{
"$project" : {
"_id" : false,
"n" : true
}
}
],
"ok" : 1
}
但是我跑了db.fs.chunks.explain("executionStats").aggregate([{$sort: {n:-1}},{$match:{n:{$lt:100000}}}, {$skip:10000}, {$limit:70}, {$project: {_id:0, n:1, files_id:1}}])
。因此,唯一的区别是还要投影未索引的files_id
字段。
同样也总结一下,该查询返回了"executionTimeMillis" : 1009
,"totalKeysExamined" : 10070
和"totalDocsExamined" : 10070
。在这种情况下,结果不是我期望的。从我的角度来看,应该是"totalKeysExamined" : 10070
和"totalDocsExamined" : 70
。
完整的输出是:
{
"stages" : [
{
"$cursor" : {
"query" : {
"n" : {
"$lt" : 100000
}
},
"sort" : {
"n" : -1
},
"limit" : NumberLong(10070),
"queryPlanner" : {
"plannerVersion" : 1,
"namespace" : "OfflineAnalysisTool.fs.chunks",
"indexFilterSet" : false,
"parsedQuery" : {
"n" : {
"$lt" : 100000
}
},
"winningPlan" : {
"stage" : "FETCH",
"inputStage" : {
"stage" : "IXSCAN",
"keyPattern" : {
"n" : 1
},
"indexName" : "files_id",
"isMultiKey" : false,
"multiKeyPaths" : {
"n" : [ ]
},
"isUnique" : false,
"isSparse" : false,
"isPartial" : false,
"indexVersion" : 2,
"direction" : "backward",
"indexBounds" : {
"n" : [
"(100000.0, -inf.0]"
]
}
}
},
"rejectedPlans" : [ ]
},
"executionStats" : {
"executionSuccess" : true,
"nReturned" : 10070,
"executionTimeMillis" : 1009,
"totalKeysExamined" : 10070,
"totalDocsExamined" : 10070,
"executionStages" : {
"stage" : "FETCH",
"nReturned" : 10070,
"executionTimeMillisEstimate" : 20,
"works" : 10070,
"advanced" : 10070,
"needTime" : 0,
"needYield" : 0,
"saveState" : 674,
"restoreState" : 674,
"isEOF" : 0,
"invalidates" : 0,
"docsExamined" : 10070,
"alreadyHasObj" : 0,
"inputStage" : {
"stage" : "IXSCAN",
"nReturned" : 10070,
"executionTimeMillisEstimate" : 10,
"works" : 10070,
"advanced" : 10070,
"needTime" : 0,
"needYield" : 0,
"saveState" : 674,
"restoreState" : 674,
"isEOF" : 0,
"invalidates" : 0,
"keyPattern" : {
"n" : 1
},
"indexName" : "files_id",
"isMultiKey" : false,
"multiKeyPaths" : {
"n" : [ ]
},
"isUnique" : false,
"isSparse" : false,
"isPartial" : false,
"indexVersion" : 2,
"direction" : "backward",
"indexBounds" : {
"n" : [
"(100000.0, -inf.0]"
]
},
"keysExamined" : 10070,
"seeks" : 1,
"dupsTested" : 0,
"dupsDropped" : 0,
"seenInvalidated" : 0
}
}
}
}
},
{
"$skip" : NumberLong(10000)
},
{
"$project" : {
"_id" : false,
"files_id" : true,
"n" : true
}
}
],
"ok" : 1
}
正如我在测试2中所写的那样,从我的角度来看,应该是"totalKeysExamined" : 10070
和"totalDocsExamined" : 70
。这是因为$sort
,$match
,$skip
和$limit
应该已经对10070个项目的索引字段进行了处理。并且$project
阶段应该在先前阶段输出的70个文档上执行,这是应该检查这70个文档的唯一阶段。