在MongoDB 2.2中引入的聚合框架,是否比map/reduce具有特殊的性能优势?
如果是的话,为什么、如何以及优化多少?
(我已经为自己进行了一次测试,性能几乎相同)
在MongoDB 2.2中引入的聚合框架,是否比map/reduce具有特殊的性能优势?
如果是的话,为什么、如何以及优化多少?
(我已经为自己进行了一次测试,性能几乎相同)
我个人运行的每个测试(包括使用你自己的数据)都显示聚合框架比映射减少快几倍,并且通常快一个数量级。
只使用你发布的1/10数据(但不是清除操作系统缓存,而是先预热缓存 - 因为我想测量聚合表现,而不是读取数据所需时间),我得到了以下结果:
MapReduce:1,058毫秒
Aggregation Framework:133毫秒
去掉聚合框架中的$match和mapReduce中的{query:}(因为两者都只使用索引,这不是我们想要测量的),并将整个数据集按key2分组后,我得到了:
MapReduce:18,803毫秒
Aggregation Framework:1,535毫秒
这些非常符合我的以前的实验结果。
我的基准测试:
== 数据生成 ==
使用 Python 生成 400 万行数据很容易,大约需要 350 字节。每个文档都有以下键:
db = Connection('127.0.0.1').test # mongo连接
random.seed(1)
for _ in range(2):
key1s = [hexlify(os.urandom(10)).decode('ascii') for _ in range(10)]
key2s = [hexlify(os.urandom(10)).decode('ascii') for _ in range(1000)]
baddata = 'some long date ' + '*' * 300
for i in range(2000):
data_list = [{
'key1': random.choice(key1s),
'key2': random.choice(key2s),
'baddata': baddata,
'value': 10,
} for _ in range(1000)]
for data in data_list:
db.testtable.save(data)
MongoDB 中的总数据大小约为 6GB(PostgreSQL 中约为 2GB)。
== 测试 ==
我做了一些测试,但只要比较结果就可以了:
注意:每次查询后,服务器都会重新启动,并清除操作系统缓存,以忽略缓存的影响。
查询:聚合所有 key1=somevalue
的行(约 20 万行),并为每个 key2
求和 value
查询:
map/reduce:
db.testtable.mapReduce(function(){emit(this.key2, this.value);}, function(key, values){var i =0; values.forEach(function(v){i+=v;}); return i; } , {out:{inline: 1}, query: {key1: '663969462d2ec0a5fc34'} })
aggregate:
db.testtable.aggregate({ $match: {key1: '663969462d2ec0a5fc34'}}, {$group: {_id: '$key2', pop: {$sum: '$value'}} })
group:
db.testtable.group({key: {key2:1}, cond: {key1: '663969462d2ec0a5fc34'}, reduce: function(obj,prev) { prev.csum += obj.value; }, initial: { csum: 0 } })