我们有一个看似简单的map/reduce作业,每天都要记录数据。在开发服务器上,我们可以在非常大量的文档上运行此作业,~1M,大约需要一分钟而没有问题。我们将作业移动到生产服务器,即 Amazon EC2 服务器,作业将以非常快的速度浏览大约 50% 的行,然后爬取其余数据。浏览数十万个文档可能需要几个小时,而不是预期的一两分钟。所以我希望我们在map/reduce工作中犯了一个明显的错误。
下面是一个示例输入文档:
{ "_id" : ObjectId("4f147a92d72b292c02000057"(, "CID" : 25, "ip" : "123.45.67.89", "b" : "Mozilla/5.0 (Macintosh;Intel Mac OS X 10_6_8( AppleWebKit/535.7 (KHTML, like Gecko( Chrome/16.0.912.63 Safari/535.7", "r" : ", "l" : "en-US,en;q=0.8", "ts" : ISODate("2012-01-16T19:29:22Z"(, "s" : 0, "CV" : "4F143A5FD72B292D7F000007", "c" : "}
我们仅查询一系列_id。
这是地图代码:
函数(( { var 浏览器 = {} ,引用 = {}; 浏览器[this.b] = { "计数":1 }; 引用[this.r] = { "计数":1 }; var objEmit = { "计数":1 ,'浏览器' : 浏览器 ,"推荐人" : 推荐人 }; var date = this._id.getTimestamp((; 日期设置小时(0(; 日期设置分钟(0(; 日期.设置秒(0(; emit({'cv' : this.cv, 'date' : date, 'cid' : this.cid }, objEmit(;};
下面是还原代码:
函数(键,发射({ 变量总计 = 0 ,浏览器 = {} ,引用 = {}; for (var i in emits( { 总计 += 发射量[i].计数; for (Var Key in emits[i].browsers( { if (emits[i].browsers.hasOwnProperty(key(( { !(浏览器[键]( && (浏览器[键] = { 计数 : 0 }(; 浏览器[键].计数 += 发射器[i].浏览器[键].计数; } } for (var key in emits[i].referrers( { if (emits[i].referrers.hasOwnProperty(key(( { !(引用[键]( &&(引荐来源网址[键] = { 计数 : 0 }(; 引用[键].计数 += 发射[i].引用线[键].计数; } } } 返回 {'count' : total, 'browsers' : browsers, 'referrers' : referrers}};
没有完成,我们将映射/归约作业输出到现有集合,并将"合并"选项设置为 true。
任何帮助都非常感谢。
由于它是在开发和生产中运行的相同代码,并且您在非常大的集合上在 dev 中运行它并且它返回得非常快,因此您怀疑您的代码可能有问题的任何特定原因?
您是否可能在微型实例上运行?如果您不知道,微型实例会限制平均 CPU 使用率,这可能会损害您的 Map-Reduce 活动,因为它会导致大量数据堆积而不允许处理它(I/O 没有以相同的方式受到限制,所以这种情况不断出现,然后 Linux 内核花费大部分时间管理它并使事情变得更糟(。
从微型切换到小型,即使CPU速度较低,也可能会对您有所帮助,因为您有恒定的CPU周期"流"可以使用(就像普通机器一样(,并且MongoDB的内部调度可能会更好地适应。
这在以前可能不是问题,因为正常的查询"峰值"持续时间不足以导致 CPU 限制打开。