0:背景:
最近在做數(shù)據(jù)統(tǒng)計(jì)部分,數(shù)據(jù)是放在MongoDB的,我們一開始的方法是從MongoDB中將數(shù)據(jù)取出,在PHP中做運(yùn)算,后面發(fā)現(xiàn)數(shù)據(jù)量大的時(shí)候,太慢了,120W的數(shù)據(jù)差不多要花30秒,后面實(shí)在受不了,于是打算使用MapReduce重構(gòu)。
1:MapReduce:
$db->command([
'mapreduce' => 'orders',
'map' => 'function(){emit("money",this.money)}',
'reduce' => 'function(key, values){return Array.sum(values)}',
'query' => $map,
'out' => 'total_money'
]);
$re = $collection->selectCollection('total_money')->find();
但是用MapReduce后,性能提升不明顯,目測(cè)只有10%左右。可能得益于省去網(wǎng)絡(luò)的傳輸成本。
1.group(先篩選再分組,不支持分片,對(duì)數(shù)據(jù)量有所限制,效率不高)
2.mapreduce(基于js引擎,單線程執(zhí)行,效率較低,適合用做后臺(tái)統(tǒng)計(jì)等)
3.aggregate(推薦) (如果你的PHP的mongodb驅(qū)動(dòng)版本需>=1.3.0,推薦你使用aggregate,性能要高很多,并且使用上要簡(jiǎn)單些,不過(guò)1.3的目前還不支持賬戶認(rèn)證模式,可以通過(guò)http://pecl.php.net/package/mongo查看更新日志和Bug)
后面發(fā)現(xiàn),樓主的mongodb驅(qū)動(dòng)剛好好能用aggregate,所以果斷使用aggregate。
2:aggregate
$collection->aggregate([
['$match' => $map],
['$group' => [
'_id' => null,
'total_money' => ['$sum' => '$money'],
'total_money_usd' => ['$sum' => '$money_usd']
]]
]);
由于樓主的MongoDB比較舊,所以不能再 $project 中調(diào)用 $sum(可以點(diǎn)我看看官方文檔)。可以可賀的是,120w數(shù)據(jù)從原來(lái)的30秒下降到18秒,體驗(yàn)大大提升。領(lǐng)導(dǎo)看數(shù)據(jù)匯總也終于不用等半天了,下一步就是搞清楚分片以及升級(jí)一下MongoDB,看看有沒(méi)有再提升的空間。