对于此查询:
db.MyCollection.explain("allPlansExecution").find({
myId: "abc123",
myBoolean: false
}).sort({
myDate: -1
}).skip(0).limit(50)
有两种选择:
indexA: { myId: 1, myDate: 1 }
indexB: { myId: 1, myDate: -1 }, { partialFilterExpression: { myBoolean: false }}
查询计划者选择indexA
而不是indexB
,即使:
indexB
的索引存储大小大约减小30%(占用更少的RAM)myBoolean
中的部分过滤器已经满足indexB
查询限制indexA
的排序方向与查询不符,而indexB
的排序方向是正确的 queryPlanner
:
"queryPlanner" : {
"plannerVersion" : 1,
"namespace" : "myDb.MyCollection",
"indexFilterSet" : false,
"parsedQuery" : {
"$and" : [
{
"myId" : {
"$eq" : "abc123"
}
},
{
"myBoolean" : {
"$eq" : false
}
}
]
},
"winningPlan" : {
"stage" : "LIMIT",
"limitAmount" : 50,
"inputStage" : {
"stage" : "FETCH",
"filter" : {
"myBoolean" : {
"$eq" : false
}
},
"inputStage" : {
"stage" : "IXSCAN",
"keyPattern" : {
"myId" : 1,
"myDate" : 1
},
"indexName" : "indexA",
"isMultiKey" : false,
"multiKeyPaths" : {
"myId" : [ ],
"myDate" : [ ]
},
"isUnique" : false,
"isSparse" : false,
"isPartial" : false,
"indexVersion" : 2,
"direction" : "backward",
"indexBounds" : {
"myId" : [
"[\"abc123\", \"abc123\"]"
],
"myDate" : [
"[MaxKey, MinKey]"
]
}
}
}
},
"rejectedPlans" : [
{
"stage" : "LIMIT",
"limitAmount" : 50,
"inputStage" : {
"stage" : "FETCH",
"filter" : {
"myBoolean" : {
"$eq" : false
}
},
"inputStage" : {
"stage" : "IXSCAN",
"keyPattern" : {
"myId" : 1,
"myDate" : -1
},
"indexName" : "indexB",
"isMultiKey" : false,
"multiKeyPaths" : {
"myId" : [ ],
"myDate" : [ ]
},
"isUnique" : false,
"isSparse" : false,
"isPartial" : true,
"indexVersion" : 2,
"direction" : "forward",
"indexBounds" : {
"myId" : [
"[\"abc123\", \"abc123\"]"
],
"myDate" : [
"[MaxKey, MinKey]"
]
}
}
}
}
]
}
我在plan ranker中找不到答案。
查询计划(有趣的是indexB
没有分数):
{
"plans" : [
{
"details" : {
"solution" : "(index-tagged expression tree: tree=Node\n---Leaf indexA, pos: 0, can combine? 1\n---Leaf \n)"
},
"reason" : {
"score" : 1.233944859813084,
"stats" : {
"stage" : "LIMIT",
"nReturned" : 50,
"executionTimeMillisEstimate" : 0,
"works" : 214,
"advanced" : 50,
"needTime" : 164,
"needYield" : 0,
"saveState" : 3,
"restoreState" : 3,
"isEOF" : 1,
"invalidates" : 0,
"limitAmount" : 50,
"inputStage" : {
"stage" : "SKIP",
"nReturned" : 50,
"executionTimeMillisEstimate" : 0,
"works" : 214,
"advanced" : 50,
"needTime" : 164,
"needYield" : 0,
"saveState" : 3,
"restoreState" : 3,
"isEOF" : 0,
"invalidates" : 0,
"skipAmount" : 0,
"inputStage" : {
"stage" : "FETCH",
"filter" : {
"myBoolean" : {
"$eq" : false
}
},
"nReturned" : 214,
"executionTimeMillisEstimate" : 0,
"works" : 214,
"advanced" : 214,
"needTime" : 0,
"needYield" : 0,
"saveState" : 3,
"restoreState" : 3,
"isEOF" : 0,
"invalidates" : 0,
"docsExamined" : 214,
"alreadyHasObj" : 0,
"inputStage" : {
"stage" : "IXSCAN",
"nReturned" : 214,
"executionTimeMillisEstimate" : 0,
"works" : 214,
"advanced" : 214,
"needTime" : 0,
"needYield" : 0,
"saveState" : 3,
"restoreState" : 3,
"isEOF" : 0,
"invalidates" : 0,
"keyPattern" : {
"myId" : 1,
"myDate" : 1
},
"indexName" : "indexA",
"isMultiKey" : false,
"multiKeyPaths" : {
"myId" : [ ],
"myDate" : [ ]
},
"isUnique" : false,
"isSparse" : false,
"isPartial" : false,
"indexVersion" : 2,
"direction" : "backward",
"indexBounds" : {
"myId" : [
"[\"abc123\", \"abc123\"]"
],
"myDate" : [
"[MaxKey, MinKey]"
]
},
"keysExamined" : 214,
"seeks" : 1,
"dupsTested" : 0,
"dupsDropped" : 0,
"seenInvalidated" : 0
}
}
}
}
},
"feedback" : {
"nfeedback" : 20,
"scores" : [
{
"score" : 2.0003
},
{
"score" : 1.0003
},
{
"score" : 1.9586333333333334
},
{
"score" : 1.0003
},
{
"score" : 2.0003
},
{
"score" : 1.0003
},
{
"score" : 1.0003
},
{
"score" : 1.9806921568627451
},
{
"score" : 1.0003
},
{
"score" : 1.9806921568627451
},
{
"score" : 1.1896939393939394
},
{
"score" : 1.9503
},
{
"score" : 1.1669666666666667
},
{
"score" : 1.0003
},
{
"score" : 2.0003
},
{
"score" : 1.0003
},
{
"score" : 1.8003
},
{
"score" : 2.0003
},
{
"score" : 2.0003
},
{
"score" : 1.0003
}
]
},
"filterSet" : false
},
{
"details" : {
"solution" : "(index-tagged expression tree: tree=Node\n---Leaf indexB, pos: 0, can combine? 1\n---Leaf \n)"
},
"reason" : {
"score" : 1.233944859813084,
"stats" : {
"stage" : "LIMIT",
"nReturned" : 50,
"executionTimeMillisEstimate" : 0,
"works" : 214,
"advanced" : 50,
"needTime" : 164,
"needYield" : 0,
"saveState" : 3,
"restoreState" : 3,
"isEOF" : 1,
"invalidates" : 0,
"limitAmount" : 50,
"inputStage" : {
"stage" : "SKIP",
"nReturned" : 50,
"executionTimeMillisEstimate" : 0,
"works" : 214,
"advanced" : 50,
"needTime" : 164,
"needYield" : 0,
"saveState" : 3,
"restoreState" : 3,
"isEOF" : 0,
"invalidates" : 0,
"skipAmount" : 0,
"inputStage" : {
"stage" : "FETCH",
"filter" : {
"myBoolean" : {
"$eq" : false
}
},
"nReturned" : 214,
"executionTimeMillisEstimate" : 0,
"works" : 214,
"advanced" : 214,
"needTime" : 0,
"needYield" : 0,
"saveState" : 3,
"restoreState" : 3,
"isEOF" : 0,
"invalidates" : 0,
"docsExamined" : 214,
"alreadyHasObj" : 0,
"inputStage" : {
"stage" : "IXSCAN",
"nReturned" : 214,
"executionTimeMillisEstimate" : 0,
"works" : 214,
"advanced" : 214,
"needTime" : 0,
"needYield" : 0,
"saveState" : 3,
"restoreState" : 3,
"isEOF" : 0,
"invalidates" : 0,
"keyPattern" : {
"myId" : 1,
"myDate" : -1
},
"indexName" : "indexB",
"isMultiKey" : false,
"multiKeyPaths" : {
"myId" : [ ],
"myDate" : [ ]
},
"isUnique" : false,
"isSparse" : false,
"isPartial" : true,
"indexVersion" : 2,
"direction" : "forward",
"indexBounds" : {
"myId" : [
"[\"abc123\", \"abc123\"]"
],
"myDate" : [
"[MaxKey, MinKey]"
]
},
"keysExamined" : 214,
"seeks" : 1,
"dupsTested" : 0,
"dupsDropped" : 0,
"seenInvalidated" : 0
}
}
}
}
},
"feedback" : {
},
"filterSet" : false
}
],
"timeOfCreation" : ISODate("2019-09-21T18:26:02.108Z"),
"ok" : 1,
"operationTime" : Timestamp(1569105839, 834),
"$clusterTime" : {
"clusterTime" : Timestamp(1569105839, 834),
"signature" : {...}
}
}
indexB
为什么不赢?feedback
没有scores
和indexB
?1.233944859813084
)相同?