我看到mongo的索引范围有些奇怪的行为。我确定我缺少基本的东西,但是我不确定它是什么。如果有人可以看看这些查询统计信息并给我一些指导,将不胜感激!
第一个问题是在复合索引中使用_id时。
给出以下索引:
db.workspaceFile.createIndex(
{
"_id" : 1, // <---- this seems to cause a problem, see executionStats below
"workspaceId" : 1,
"parent._id" : 1,
"documentParent._id" : 1,
"archiveParent._id" : 1
},
{name:'testIndexA'}
);
db.workspaceFile.createIndex(
{
"workspaceId" : 1,
"parent._id" : 1,
"documentParent._id" : 1,
"archiveParent._id" : 1
},
{name:'testIndexB'}
);
运行查询:
var workspaceId = "5bc0ac10abe03f0d47ea0363";
var fileId = ObjectId("5bc0ac3cabe03f0d47ea0379");
var fileFamilyQuery = {
"$and": [{
"workspaceId": workspaceId,
"$or": [{
"_id": fileId,
}, {
"parent._id": fileId
}, {
"documentParent._id": fileId
}, {
"archiveParent._id": fileId
}]
}]
};
db.workspaceFile.find(fileFamilyQuery).sort({"_id":-1}).hint(indexName).explain('executionStats')
当应用于两个索引时,会产生一些非常不同的执行状态。
testIndexA:
db.workspaceFile.find(fileFamilyQuery).sort({"_id":-1}).hint('testIndexA').explain('executionStats')
{
"queryPlanner" : {
"plannerVersion" : 1,
"namespace" : "storage.workspaceFile",
"indexFilterSet" : false,
"parsedQuery" : {
"$and" : [
{
"$or" : [
{
"_id" : {
"$eq" : ObjectId("5bc0ac3cabe03f0d47ea0379")
}
},
{
"archiveParent._id" : {
"$eq" : ObjectId("5bc0ac3cabe03f0d47ea0379")
}
},
{
"documentParent._id" : {
"$eq" : ObjectId("5bc0ac3cabe03f0d47ea0379")
}
},
{
"parent._id" : {
"$eq" : ObjectId("5bc0ac3cabe03f0d47ea0379")
}
}
]
},
{
"workspaceId" : {
"$eq" : "5bc0ac10abe03f0d47ea0363"
}
}
]
},
"winningPlan" : {
"stage" : "FETCH",
"filter" : {
"$and" : [
{
"$or" : [
{
"_id" : {
"$eq" : ObjectId("5bc0ac3cabe03f0d47ea0379")
}
},
{
"archiveParent._id" : {
"$eq" : ObjectId("5bc0ac3cabe03f0d47ea0379")
}
},
{
"documentParent._id" : {
"$eq" : ObjectId("5bc0ac3cabe03f0d47ea0379")
}
},
{
"parent._id" : {
"$eq" : ObjectId("5bc0ac3cabe03f0d47ea0379")
}
}
]
},
{
"workspaceId" : {
"$eq" : "5bc0ac10abe03f0d47ea0363"
}
}
]
},
"inputStage" : {
"stage" : "IXSCAN",
"keyPattern" : {
"_id" : 1,
"workspaceId" : 1,
"parent._id" : 1,
"documentParent._id" : 1,
"archiveParent._id" : 1
},
"indexName" : "testIndexA",
"isMultiKey" : false,
"multiKeyPaths" : {
"_id" : [ ],
"workspaceId" : [ ],
"parent._id" : [ ],
"documentParent._id" : [ ],
"archiveParent._id" : [ ]
},
"isUnique" : false,
"isSparse" : false,
"isPartial" : false,
"indexVersion" : 2,
"direction" : "backward",
"indexBounds" : {
"_id" : [
"[MaxKey, MinKey]"
],
"workspaceId" : [
"[MaxKey, MinKey]"
],
"parent._id" : [
"[MaxKey, MinKey]"
],
"documentParent._id" : [
"[MaxKey, MinKey]"
],
"archiveParent._id" : [
"[MaxKey, MinKey]"
]
}
}
},
"rejectedPlans" : [ ]
},
"executionStats" : {
"executionSuccess" : true,
"nReturned" : 1,
"executionTimeMillis" : 2304,
"totalKeysExamined" : 552487,
"totalDocsExamined" : 552487,
"executionStages" : {
"stage" : "FETCH",
"filter" : {
"$and" : [
{
"$or" : [
{
"_id" : {
"$eq" : ObjectId("5bc0ac3cabe03f0d47ea0379")
}
},
{
"archiveParent._id" : {
"$eq" : ObjectId("5bc0ac3cabe03f0d47ea0379")
}
},
{
"documentParent._id" : {
"$eq" : ObjectId("5bc0ac3cabe03f0d47ea0379")
}
},
{
"parent._id" : {
"$eq" : ObjectId("5bc0ac3cabe03f0d47ea0379")
}
}
]
},
{
"workspaceId" : {
"$eq" : "5bc0ac10abe03f0d47ea0363"
}
}
]
},
"nReturned" : 1,
"executionTimeMillisEstimate" : 2240,
"works" : 552488,
"advanced" : 1,
"needTime" : 552486,
"needYield" : 0,
"saveState" : 4316,
"restoreState" : 4316,
"isEOF" : 1,
"invalidates" : 0,
"docsExamined" : 552487,
"alreadyHasObj" : 0,
"inputStage" : {
"stage" : "IXSCAN",
"nReturned" : 552487,
"executionTimeMillisEstimate" : 420,
"works" : 552488,
"advanced" : 552487,
"needTime" : 0,
"needYield" : 0,
"saveState" : 4316,
"restoreState" : 4316,
"isEOF" : 1,
"invalidates" : 0,
"keyPattern" : {
"_id" : 1,
"workspaceId" : 1,
"parent._id" : 1,
"documentParent._id" : 1,
"archiveParent._id" : 1
},
"indexName" : "testIndexA",
"isMultiKey" : false,
"multiKeyPaths" : {
"_id" : [ ],
"workspaceId" : [ ],
"parent._id" : [ ],
"documentParent._id" : [ ],
"archiveParent._id" : [ ]
},
"isUnique" : false,
"isSparse" : false,
"isPartial" : false,
"indexVersion" : 2,
"direction" : "backward",
"indexBounds" : {
"_id" : [
"[MaxKey, MinKey]"
],
"workspaceId" : [
"[MaxKey, MinKey]"
],
"parent._id" : [
"[MaxKey, MinKey]"
],
"documentParent._id" : [
"[MaxKey, MinKey]"
],
"archiveParent._id" : [
"[MaxKey, MinKey]"
]
},
"keysExamined" : 552487,
"seeks" : 1,
"dupsTested" : 0,
"dupsDropped" : 0,
"seenInvalidated" : 0
}
}
},
"serverInfo" : {
"host" : "mongo-01",
"port" : 27017,
"version" : "3.6.8",
"gitVersion" : "6bc9ed599c3fa164703346a22bad17e33fa913e4"
},
"ok" : 1,
"operationTime" : Timestamp(1539531475, 1),
"$clusterTime" : {
"clusterTime" : Timestamp(1539531475, 1),
"signature" : {
"hash" : BinData(0,"GRxYv+0IJdXEHtaoVJkZfVYcSAc="),
"keyId" : NumberLong("6610403106079375362")
}
}
}
testIndexB:
db.workspaceFile.find(fileFamilyQuery).sort({"_id":-1}).hint('testIndexB').explain('executionStats')
{
"queryPlanner" : {
"plannerVersion" : 1,
"namespace" : "storage.workspaceFile",
"indexFilterSet" : false,
"parsedQuery" : {
"$and" : [
{
"$or" : [
{
"_id" : {
"$eq" : ObjectId("5bc0ac3cabe03f0d47ea0379")
}
},
{
"archiveParent._id" : {
"$eq" : ObjectId("5bc0ac3cabe03f0d47ea0379")
}
},
{
"documentParent._id" : {
"$eq" : ObjectId("5bc0ac3cabe03f0d47ea0379")
}
},
{
"parent._id" : {
"$eq" : ObjectId("5bc0ac3cabe03f0d47ea0379")
}
}
]
},
{
"workspaceId" : {
"$eq" : "5bc0ac10abe03f0d47ea0363"
}
}
]
},
"winningPlan" : {
"stage" : "SORT",
"sortPattern" : {
"_id" : -1
},
"inputStage" : {
"stage" : "SORT_KEY_GENERATOR",
"inputStage" : {
"stage" : "FETCH",
"filter" : {
"$or" : [
{
"_id" : {
"$eq" : ObjectId("5bc0ac3cabe03f0d47ea0379")
}
},
{
"archiveParent._id" : {
"$eq" : ObjectId("5bc0ac3cabe03f0d47ea0379")
}
},
{
"documentParent._id" : {
"$eq" : ObjectId("5bc0ac3cabe03f0d47ea0379")
}
},
{
"parent._id" : {
"$eq" : ObjectId("5bc0ac3cabe03f0d47ea0379")
}
}
]
},
"inputStage" : {
"stage" : "IXSCAN",
"keyPattern" : {
"workspaceId" : 1,
"parent._id" : 1,
"documentParent._id" : 1,
"archiveParent._id" : 1
},
"indexName" : "testIndexB",
"isMultiKey" : false,
"multiKeyPaths" : {
"workspaceId" : [ ],
"parent._id" : [ ],
"documentParent._id" : [ ],
"archiveParent._id" : [ ]
},
"isUnique" : false,
"isSparse" : false,
"isPartial" : false,
"indexVersion" : 2,
"direction" : "forward",
"indexBounds" : {
"workspaceId" : [
"[\"5bc0ac10abe03f0d47ea0363\", \"5bc0ac10abe03f0d47ea0363\"]"
],
"parent._id" : [
"[MinKey, MaxKey]"
],
"documentParent._id" : [
"[MinKey, MaxKey]"
],
"archiveParent._id" : [
"[MinKey, MaxKey]"
]
}
}
}
}
},
"rejectedPlans" : [ ]
},
"executionStats" : {
"executionSuccess" : true,
"nReturned" : 1,
"executionTimeMillis" : 0,
"totalKeysExamined" : 16,
"totalDocsExamined" : 16,
"executionStages" : {
"stage" : "SORT",
"nReturned" : 1,
"executionTimeMillisEstimate" : 0,
"works" : 20,
"advanced" : 1,
"needTime" : 18,
"needYield" : 0,
"saveState" : 0,
"restoreState" : 0,
"isEOF" : 1,
"invalidates" : 0,
"sortPattern" : {
"_id" : -1
},
"memUsage" : 638,
"memLimit" : 33554432,
"inputStage" : {
"stage" : "SORT_KEY_GENERATOR",
"nReturned" : 1,
"executionTimeMillisEstimate" : 0,
"works" : 18,
"advanced" : 1,
"needTime" : 16,
"needYield" : 0,
"saveState" : 0,
"restoreState" : 0,
"isEOF" : 1,
"invalidates" : 0,
"inputStage" : {
"stage" : "FETCH",
"filter" : {
"$or" : [
{
"_id" : {
"$eq" : ObjectId("5bc0ac3cabe03f0d47ea0379")
}
},
{
"archiveParent._id" : {
"$eq" : ObjectId("5bc0ac3cabe03f0d47ea0379")
}
},
{
"documentParent._id" : {
"$eq" : ObjectId("5bc0ac3cabe03f0d47ea0379")
}
},
{
"parent._id" : {
"$eq" : ObjectId("5bc0ac3cabe03f0d47ea0379")
}
}
]
},
"nReturned" : 1,
"executionTimeMillisEstimate" : 0,
"works" : 17,
"advanced" : 1,
"needTime" : 15,
"needYield" : 0,
"saveState" : 0,
"restoreState" : 0,
"isEOF" : 1,
"invalidates" : 0,
"docsExamined" : 16,
"alreadyHasObj" : 0,
"inputStage" : {
"stage" : "IXSCAN",
"nReturned" : 16,
"executionTimeMillisEstimate" : 0,
"works" : 17,
"advanced" : 16,
"needTime" : 0,
"needYield" : 0,
"saveState" : 0,
"restoreState" : 0,
"isEOF" : 1,
"invalidates" : 0,
"keyPattern" : {
"workspaceId" : 1,
"parent._id" : 1,
"documentParent._id" : 1,
"archiveParent._id" : 1
},
"indexName" : "testIndexB",
"isMultiKey" : false,
"multiKeyPaths" : {
"workspaceId" : [ ],
"parent._id" : [ ],
"documentParent._id" : [ ],
"archiveParent._id" : [ ]
},
"isUnique" : false,
"isSparse" : false,
"isPartial" : false,
"indexVersion" : 2,
"direction" : "forward",
"indexBounds" : {
"workspaceId" : [
"[\"5bc0ac10abe03f0d47ea0363\", \"5bc0ac10abe03f0d47ea0363\"]"
],
"parent._id" : [
"[MinKey, MaxKey]"
],
"documentParent._id" : [
"[MinKey, MaxKey]"
],
"archiveParent._id" : [
"[MinKey, MaxKey]"
]
},
"keysExamined" : 16,
"seeks" : 1,
"dupsTested" : 0,
"dupsDropped" : 0,
"seenInvalidated" : 0
}
}
}
}
},
"serverInfo" : {
"host" : "mongo-01",
"port" : 27017,
"version" : "3.6.8",
"gitVersion" : "6bc9ed599c3fa164703346a22bad17e33fa913e4"
},
"ok" : 1,
"operationTime" : Timestamp(1539531535, 1),
"$clusterTime" : {
"clusterTime" : Timestamp(1539531535, 1),
"signature" : {
"hash" : BinData(0,"swIdZFzQUkiE8xWil++cN5JU2Xw="),
"keyId" : NumberLong("6610403106079375362")
}
}
}
使用testIndexA时,将检查552,487个键,执行时间为2,304ms。 indexBounds不包含查询中定义的任何参数:
"indexBounds" : {
"_id" : [
"[MaxKey, MinKey]"
],
"workspaceId" : [
"[MaxKey, MinKey]"
],
"parent._id" : [
"[MaxKey, MinKey]"
],
"documentParent._id" : [
"[MaxKey, MinKey]"
],
"archiveParent._id" : [
"[MaxKey, MinKey]"
]
}
使用testIndexB时,仅检查16个键,执行时间为0ms。 indexBounds看起来更好,但仍然缺少fileId参数:
"indexBounds" : {
"workspaceId" : [
"[\"5bc0ac10abe03f0d47ea0363\", \"5bc0ac10abe03f0d47ea0363\"]"
],
"parent._id" : [
"[MinKey, MaxKey]"
],
"documentParent._id" : [
"[MinKey, MaxKey]"
],
"archiveParent._id" : [
"[MinKey, MaxKey]"
]
}
我很困惑,为什么在testIndexA中包含'_id'字段会导致工作区ID不绑定到索引扫描。另一个索引(testIndexB)更好,因为正在使用工作区ID,但不绑定文件ID字段仍然存在问题。