我有一个 MongoDB 用于存储这样的结果
{_id, type, imei, lat, lng, spd, dir, time}
{_id, type, imei, lac, cid, time}
如果type
是f
第一个则使用,如果是l
第二个则使用。
这是索引:
"indexSizes" : {
"_id_" : 340358704,
"imei_1" : 614508160,
"type_1" : 183616608,
"type_1_imei_1" : 349793808
},
Collection 有大约 1000 万份文件。我有很多关于type
andimei
的查询,目前只有类型f
在应用程序中使用。
这是日志文件中的一行
Sun Aug 31 19:14:39.402 [conn782250] query xxyyxx.locs query: { $query: { $and: [ { imei: "359710042581612" }, { type: "f" } ] }, $orderby: { time: -1 } } ntoreturn:1 ntoskip:0 nscanned:140455 scanAndOrder:1 keyUpdates:0 numYields: 59 locks(micros) r:38456361 nreturned:1 reslen:159 19727ms
这花了大约20秒,太多了。
我需要进一步优化我的收藏。这在 Web 应用程序中使用,有时像这样的查询会执行 10imei
秒,大约需要 200 秒,这可能会导致超时。这是异步执行的(ajax),但仍然有太多的等待时间。
这里的专家的任何帮助都非常受欢迎。
另外,如果您认为我遗漏了什么,请务必索取更多信息。
提前致谢
顺便说一句,我将 PHP 用于 Web 部件(Laravel 框架和https://github.com/jenssegers/Laravel-MongoDB)
编辑:这是explain
(已删除)
EDIT2:创建更好的索引后:
MongoDB shell version: 2.4.9
connecting to: test
> use gpstracker
switched to db gpstracker
> db.locs.stats()
{
"ns" : "gpstracker.locs",
"count" : 10137188,
"size" : 1400944384,
"avgObjSize" : 138.19852053646434,
"storageSize" : 1580060672,
"numExtents" : 19,
"nindexes" : 2,
"lastExtentSize" : 415145984,
"paddingFactor" : 1,
"systemFlags" : 0,
"userFlags" : 0,
"totalIndexSize" : 826806176,
"indexSizes" : {
"_id_" : 359997456,
"type_1_imei_1_time_-1" : 466808720
},
"ok" : 1
}
> db.locs.find({ $and: [ { imei: "359710042581612" }, { type: "f" } ] }).explain()
{
"cursor" : "BtreeCursor type_1_imei_1_time_-1",
"isMultiKey" : false,
"n" : 150158,
"nscannedObjects" : 150158,
"nscanned" : 150158,
"nscannedObjectsAllPlans" : 150158,
"nscannedAllPlans" : 150158,
"scanAndOrder" : false,
"indexOnly" : false,
"nYields" : 329,
"nChunkSkips" : 0,
"millis" : 128173,
"indexBounds" : {
"type" : [
[
"f",
"f"
]
],
"imei" : [
[
"359710042581612",
"359710042581612"
]
],
"time" : [
[
{
"$maxElement" : 1
},
{
"$minElement" : 1
}
]
]
},
"server" : "CDSX001:27017"
}
您的查询正在使用索引来获取结果,但之后需要对它们进行排序,这是一项昂贵的操作。
"scanAndOrder" : true,scanAndOrder 是一个布尔值,当查询不能使用索引中文档的顺序返回排序结果时为 true:MongoDB 必须在从游标接收文档后对文档进行排序。
解决方案是在 {imei:1, type:1, time:-1} 或 {type:1, imei:1, time:-1} 上应用索引(索引上的 imei,type 顺序取决于 imei 和类型选择性)