MongoDb提高了聚合框架的性能
我收集了70亿份数据。 我的数据模型是: {“_id”:ObjectId(“515921e3bbea58d25eb07b22”),“serverId”:0, “计数器ID”:0,“插入”:ISODate(“2013-03-21T00:26:30Z”), “对应值”:0.03256159112788737,“最小值”:-29.96743840887113, “最大值”:20.032561591127887} 我有两个索引serverId,counterId; 我的问题是: {$match:{'inserted':{$gte:新日期(“2013-03-21T00:00:00Z”),$lt: 新日期(“2013-03-22T10:00:00Z”)}},{$group: {{u id:{serverId:'$serverId',counterId:'$counterId'},avgValue:{$avg: “$counterValue”}} 查找平均计数器值,按serverId、counterId分组,并在特定日期之间插入 但它需要13秒我需要它必须需要1秒MongoDb提高了聚合框架的性能,mongodb,Mongodb,我收集了70亿份数据。 我的数据模型是: {“_id”:ObjectId(“515921e3bbea58d25eb07b22”),“serverId”:0, “计数器ID”:0,“插入”:ISODate(“2013-03-21T00:26:30Z”), “对应值”:0.03256159112788737,“最小值”:-29.96743840887113, “最大值”:20.032561591127887} 我有两个索引serverId,counterId; 我的问题是: {$match:{'in
我该怎么做呢?为什么不在插入的列上添加索引呢?它将有一些性能增益。插入当天的索引将帮助您快速获取数据,如此处文档中所指定:。指数将被用来购买美元匹配放在开始。因此,在插入的列上有一个索引您的索引在以下方面是无用的:
{$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万条记录,你仍然可以从框架中看到糟糕的性能。这是因为,归根结底,没有简单的方法可以做到这一点;这是缓慢的,因为你有多少聚合
更好的替代方法可能是使用预聚合报告,它将通过其他机制(如在客户端中保存)以您需要的形式提供数据,以创建性能查询。您对插入的字段进行查询,因此插入的字段应具有索引。其他的是无用的(对于这个查询) 如果您想要进行一个完整的索引查询,这将帮助您大大提高性能,那么您还应该将字段放在您查询的索引中。在这种情况下,它还可以使用索引来获取值,而不是去访问每个单独的文档(在磁盘上,可能考虑到文档的数量),这将减慢查询速度 因此,您应该在聚合查询中包含
$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字段,该字段不在索引中,因此它将转到每个单独的文档,您不需要的内容。您的工作集大小与RAM的对比是多少?如果要避免完整的集合扫描,您绝对需要为插入的
列编制索引。