Mongo查找查询需要2分钟

我收集了大约75,000个文件。

数据库的总大小约为45GB。
在75k文档中,大约45k是每个900KB(大约42GB),其余的文档大约是120KB。

每个文档都映射到其他集合中的custId ObjectId,并且具有一个索引的timestamp

现在我需要为上个月的特定客户获取文档。 这个数字大约是5500个文档。 这个custId有大小约120 KB的小文档。

以下是我的查询:

 db.mycollection.find( { custId:ObjectId("CUST_OBJECT_ID_HERE"), timestamp:{$gte:one_month_ago_date, $lt:current_date} }).sort({timestamp:-1}) 

仍然查询需要2分钟来获取所有logging。 是因为文件的数量还是文件的大小? 有没有办法解决这个问题?

注意:从nodejs发起查询需要2分钟。 如果我在mongo shell上启动它,它会很快返回,但可能是因为它刚刚取得了前50条logging。 当我将.count()附加到mongo shell上的查询时,需要2分钟才能返回count。

更新:
索引细节:

 "wiredTiger" : { "nindexes" : 3, "totalIndexSize" : 2396160, "indexSizes" : { "_id_" : 1138688, "custId_1" : 598016, "timestamp_1" : 659456 } } 

说明输出:(有点)

 { "queryPlanner" : { "plannerVersion" : 1, "namespace" : "mydb.mycollection", "indexFilterSet" : false, "parsedQuery" : { "$and" : [ { "custId" : { "$eq" : ObjectId("CUST_OBJECT_ID_HERE") } }, { "timestamp" : { "$lt" : ISODate("2017-05-15T14:20:04.393Z") } }, { "timestamp" : { "$gte" : ISODate("2017-04-15T14:20:04.393Z") } } ] }, "winningPlan" : { "stage" : "FETCH", "filter" : { "custId" : { "$eq" : ObjectId("CUST_OBJECT_ID_HERE") } }, "inputStage" : { "stage" : "IXSCAN", "keyPattern" : { "timestamp" : 1 }, "indexName" : "timestamp_1", "isMultiKey" : false, "isUnique" : false, "isSparse" : false, "isPartial" : false, "indexVersion" : 1, "direction" : "backward", "indexBounds" : { "timestamp" : [ "(new Date(1494858004393), new Date(1492266004393)]" ] } } }, "rejectedPlans" : [ { "stage" : "SORT", "sortPattern" : { "timestamp" : -1 }, "inputStage" : { "stage" : "SORT_KEY_GENERATOR", "inputStage" : { "stage" : "FETCH", "filter" : { "$and" : [ { "timestamp" : { "$lt" : ISODate("2017-05-15T14:20:04.393Z") } }, { "timestamp" : { "$gte" : ISODate("2017-04-15T14:20:04.393Z") } } ] }, "inputStage" : { "stage" : "IXSCAN", "keyPattern" : { "custId" : 1 }, "indexName" : "custId_1", "isMultiKey" : false, "isUnique" : false, "isSparse" : false, "isPartial" : false, "indexVersion" : 1, "direction" : "forward", "indexBounds" : { "custId" : [ "[ObjectId('CUST_OBJECT_ID_HERE'), ObjectId('CUST_OBJECT_ID_HERE')]" ] } } } } } ] }, "serverInfo" : { "host" : "test-machine", "port" : 27017, "version" : "3.2.12", "gitVersion" : "REMOVED_BY_OP" }, "ok" : 1 } 

试试这个索引:

 db.mycollection.createIndex({custId:1,timestamp:1}, {background:true}) 

这是什么索引!

为timestamp和custId创build索引(复合索引与两者都将是最有效的),你就好了。 由于按时间戳sorting,在复合索引中,使时间戳成为第一个(顺序重要)


这是在mongo中创build复合索引的代码:

 const mongoose = require('mongoose'); const Schema = mongoose.Schema; const userSchema = new Schema({ //... }); userSchema.index({timestamp: 1, custId: 1}); mongoose.model('User', userSchema); module.exports = userSchema; 

上面的答案都是完全正确的。 只要把我的2美分。 这个答案很大程度上取决于你可用的内存,如果你需要返回的信息是“实时的”,或者信息可以以某种方式被caching。

Mongodb是臭名昭着的内存使用。 (我喜欢mongodb,但记忆是阿基里斯脚后跟)。 其次,如上所述,在查询之前 ,您可以做的任何改进查询结果的工作都是时间,读取和核心使用的一大优势。 当涉及到存储文档时,您可能(或将要)find正确设置的Rediscaching,这也将极大地帮助您降低响应时间。

显然这需要内存,在你的情况下需要一个平衡(包括负载平衡)。 这是适当的内存,速度和磁盘使用(即使它是SSD)的适当组合,这将有助于平衡这些查询请求与系统的要求。

希望有点帮助。