我正在运行MongoDB 2.6.7版。我有一个大约有700万份文件的集合。每个文档上都有一个guid字段,这是唯一的。这是一个示例查询,我希望它应该使用guid索引,而是在不同的索引上使用一些疯狂的查询:
2015-02-02T23:05:13.349+0000 [conn6716672] query MyDB.persistentObject query:
{ query:
{ guid: { $in: [ "some_guid" ] },
ownerId: { $in: [ 0, 1, 1025252577, 994090559, 1317724, 1088410057,
1125454113, 1122731922, 994089725, 1122732678, 1317394, 1129549288,1122731600,
1312755, 1115032827, 1122461088, 1315404, 1025251224, 1124535620, 1059802590,
1124023810, 1125620352, 991434980, 1115022865, 1115031571, 1124514149,
1124534953, 1124534178, 1126176542, 1124533461, 149095604, 810047314,
1069908537 ] } },
orderby: { updated: -1 },
planSummary: IXSCAN { ownerId: 1.0, updated: -1.0 }, IXSCAN { ownerId: 1.0, updated: -1.0 },
IXSCAN { ownerId: 1.0, updated: -1.0 }, IXSCAN { ownerId: 1.0, updated: -1.0 },
IXSCAN { ownerId: 1.0, updated: -1.0 }, IXSCAN { ownerId: 1.0, updated: -1.0 },
IXSCAN { ownerId: 1.0, updated: -1.0 }, IXSCAN { ownerId: 1.0, updated: -1.0 },
IXSCAN { ownerId: 1.0, updated: -1.0 }, IXSCAN { ownerId: 1.0, updated: -1.0 },
IXSCAN { ownerId: 1.0, updated: -1.0 }, IXSCAN { ownerId: 1.0, updated: -1.0 },
IXSCAN { ownerId: 1.0, updated: -1.0 }, IXSCAN { ownerId: 1.0, updated: -1.0 },
IXSCAN { ownerId: 1.0, updated: -1.0 }, IXSCAN { ownerId: 1.0, updated: -1.0 },
IXSCAN { ownerId: 1.0, updated: -1.0 }, IXSCAN { ownerId: 1.0, updated: -1.0 },
IXSCAN { ownerId: 1.0, updated: -1.0 }, IXSCAN { ownerId: 1.0, updated: -1.0 },
IXSCAN { ownerId: 1.0, updated: -1.0 }, IXSCAN { ownerId: 1.0, updated: -1.0 },
IXSCAN { ownerId: 1.0, updated: -1.0 }, IXSCAN { ownerId: 1.0, updated: -1.0 },
IXSCAN { ownerId: 1.0, updated: -1.0 }, IXSCAN { ownerId: 1.0, updated: -1.0 },
IXSCAN { ownerId: 1.0, updated: -1.0 }, IXSCAN { ownerId: 1.0, updated: -1.0 },
IXSCAN { ownerId: 1.0, updated: -1.0 }, IXSCAN { ownerId: 1.0, updated: -1.0 },
IXSCAN { ownerId: 1.0, updated: -1.0 }, IXSCAN { ownerId: 1.0, updated: -1.0 },
IXSCAN { ownerId: 1.0, updated: -1.0 }
ntoreturn:500 ntoskip:0 nscanned:6739394 nscannedObjects:6739394
keyUpdates:0 numYields:7434 locks(micros) r:374790754 nreturned:1 reslen:55 274222ms
以下是该集合的索引列表:
shard1:PRIMARY> db.MyDB.getIndexes()
[
{
"v" : 1,
"key" : {
"_id" : 1
},
"name" : "_id_",
"ns" : "MyDB.persistentObject"
},
{
"v" : 1,
"key" : {
"id" : 1,
"updated" : -1
},
"name" : "id_updated_index",
"ns" : "MyDB.persistentObject",
"dropDups" : false,
"sparse" : false
},
{
"v" : 1,
"key" : {
"guid" : 1
},
"name" : "guid",
"ns" : "MyDB.persistentObject",
"dropDups" : false,
"sparse" : false
},
{
"v" : 1,
"key" : {
"ownerId" : 1,
"updated" : -1
},
"name" : "ownerId_1_updated_-1",
"ns" : "MyDB.persistentObject"
}
]
由于只有一个guid请求,但许多ownerIds,我希望使用guid索引。如果使用它,将导致nscanned=1
并且结果非常快。相反,选择了一个非常浪费的指数。在不同的查询中反复选择这个坏索引,mongo实例变得完全残缺。
db.stats():
{
"db" : "MyDB",
"collections" : 7,
"objects" : 6761839,
"avgObjSize" : 496.46051968998376,
"dataSize" : 3356986104,
"storageSize" : 3918581760,
"numExtents" : 28,
"indexes" : 14,
"indexSize" : 983450160,
"fileSize" : 10666115072,
"nsSizeMB" : 16,
"dataFileVersion" : {
"major" : 4,
"minor" : 5
},
"extentFreeList" : {
"num" : 10,
"totalSize" : 475508736
},
"ok" : 1
}
db.serverStatus()MEM:
{
"bits" : 64,
"resident" : 946,
"virtual" : 38232,
"supported" : true,
"mapped" : 18409,
"mappedWithJournal" : 36818
}
正确选择guid的示例解释计划。大多数时候,当我运行解释时,它会做我想要的。但是,似乎每天都会发生一些事情,它开始选择糟糕的指数并最终陷入死亡螺旋。
db.persistentObject.find({ guid: { $in: [ "some_guid" ] }, ownerId: { $in: [ 0, 1, 1025252577, 994090559, 1317724, 1088410057, 1125454113, 1122731922, 994089725,
1122732678, 1317394, 1129549288,1122731600, 1312755, 1115032827, 1122461088, 1315404, 1025251224, 1124535620, 1059802590, 1124023810, 1125620352, 991434980, 1115022865,
1115031571, 1124514149, 1124534953, 1124534178, 1126176542, 1124533461, 149095604, 810047314, 1069908537 ]}, orderby: { updated: -1 }}).explain()
{
"cursor" : "BtreeCursor guid",
"isMultiKey" : false,
"n" : 0,
"nscannedObjects" : 1,
"nscanned" : 1,
"nscannedObjectsAllPlans" : 4,
"nscannedAllPlans" : 4,
"scanAndOrder" : false,
"indexOnly" : false,
"nYields" : 1,
"nChunkSkips" : 0,
"millis" : 20,
"indexBounds" : {
"guid" : [
[
"some_guid",
"some_guid"
]
]
},
"server" : "myServer:27018",
"filterSet" : false,
"stats" : {
"type" : "KEEP_MUTATIONS",
"works" : 3,
"yields" : 1,
"unyields" : 1,
"invalidates" : 0,
"advanced" : 0,
"needTime" : 1,
"needFetch" : 0,
"isEOF" : 1,
"children" : [
{
"type" : "FETCH",
"works" : 2,
"yields" : 1,
"unyields" : 1,
"invalidates" : 0,
"advanced" : 0,
"needTime" : 1,
"needFetch" : 0,
"isEOF" : 1,
"alreadyHasObj" : 0,
"forcedFetches" : 0,
"matchTested" : 0,
"children" : [
{
"type" : "IXSCAN",
"works" : 2,
"yields" : 1,
"unyields" : 1,
"invalidates" : 0,
"advanced" : 1,
"needTime" : 0,
"needFetch" : 0,
"isEOF" : 1,
"keyPattern" : "{ guid: 1 }",
"isMultiKey" : 0,
"boundsVerbose" : "field #0['guid']: [\"some_guid\", \"some_guid\"]",
"yieldMovedCursor" : 0,
"dupsTested" : 0,
"dupsDropped" : 0,
"seenInvalidated" : 0,
"matchTested" : 0,
"keysExamined" : 1,
"children" : [ ]
}
]
}
]
}
}
答案 0 :(得分:0)
它似乎已选择索引ownerId_1_updated_-1作为查询的最佳候选者,因为这可以帮助查询的排序部分。这仍将导致扫描大量文档,因为它必须与guid字段匹配。
尝试将guid字段添加到ownerId_1_updated_-1索引
{
"v" : 1,
"key" : {
"guid" : 1,
"ownerId" : 1,
"updated" : -1
},
"name" : "guid_1_ownerId_1_updated_-1",
"ns" : "MyDB.persistentObject"
}