2013-04-01 109 views
0

我的收藏中有70亿数据。 我的数据模型是:MongoDb增加聚合框架性能

{ “_id”:的ObjectId( “515921e3bbea58d25eb07b22”), “服务器ID”:0, “counterId”:0 “插入”:ISODate(“2013-03-21T00: 26:30Z“), ”counterValue“:0.03256159112788737,”min“:-29.967438408872113, ”max“:20.032561591127887}。

我有2个索引serverId,counterId; 和我的查询是:

{$比赛:{ '插入':{$ GTE:新的日期( “2013-03-21T00:00:00Z”),$ LT: 新的日期(“2013 -03-22T10:00:00Z“)}}},{$ group: {_id:{serverId:'$ serverId',counterId:'$ counterId'},avgValue:{$ avg: '$ counterValue'} }}

查找平均counterValues,按照serverId,counterId分组,插入到特定日期之间。

但它需要13秒,我需要它需要1秒。

我该怎么做?

+0

什么是你的工作集大小vs RAM?如果您想避免完整的收集扫描,您绝对需要为“插入”列编制索引。 – WiredPrairie

回答

0

你的指数是无用的:

{$match:{ 'inserted':{$gte: new Date("2013-03-21T00:00:00Z") , $lt: new Date("2013-03-22T10:00:00Z") } } }, 
{$group : {_id:{serverId:'$serverId', counterId:'$counterId'} ,avgValue:{ $avg : '$counterValue'}}} 

由于$group功能是在内存中,不使用索引,但是,$match即可。如果你把一个索引作为@Devesh说的话,在inserted字段你应该会得到更好的性能。

但是,如果这个结果集很大,比如说那70亿条记录中的100万条记录,那么您仍然可以在框架中看到糟糕的表现。这是因为,在一天结束时,没有简单的方法来做到这一点;这是因为你汇总了多少。

一个更好的选择可能是使用预先汇总的报告,它将通过一些其他机制(如保存在客户端中)以您需要的形式提供数据以创建高性能查询。

1

您可以在插入的字段上进行查询,因此插入的字段应该具有索引。其他人没用(对于这个查询)。

如果你想做一个完整的索引查询来帮助你提高性能,你也应该把这些字段放在你查询的索引中。在这种情况下,它也可以使用索引来获取值,而不是每个单独文档(在磁盘上可能考虑大量文档),这会减慢查询速度。

所以你应该包括$project聚合查询。指标应该是:

{inserted:1, serverId:1, counterId:1, counterValue:1} 

和查询:

{ 
    $match:{ 'inserted':{$gte: new Date("2013-03-21T00:00:00Z") , $lt: new Date("2013-03-22T10:00:00Z") } } }, 
    $project: {'serverId':1, 'counterId':1, 'counterValue':1, '_id':0}, 
    {$group : {_id:{serverId:'$serverId', counterId:'$counterId'} ,avgValue:{ $avg : '$counterValue'}} 
} 

也注意到_id:0。默认情况下,返回_id字段,该字段不在索引中,因此它将转到每个单独的文档,您不需要。