2013-04-01 147 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字段,該字段不在索引中,因此它將轉到每個單獨的文檔,您不需要。