我现在正在做一些数据分析测试,在第一个非常简单的测试中,我得到了非常奇怪的结果。
想法如下:来自互联网访问日志(每个访问都有一个文档的集合,用于测试9000万个文档)。我想按域获取访问次数(MySQL中的GROUP by),并获得访问次数最多的10个域
我用JavaScript编写的脚本非常简单:
/* Counts each domain url */
m = function () {
emit(this.domain, 1 );
}
r = function (key, values) {
total = 0;
for (var i in values) {
total += Number(i);
}
return total;
}
/* Store of visits per domain statistics on NonFTP_Access_log_domain_visits collection */
res = db.NonFTP_Access_log.mapReduce(m, r, { out: { replace : "NonFTP_Access_log_domain_visits" } } );
db.NonFTP_Access_log_domain_visits.ensureIndex({ "value": 1});
db.NonFTP_Access_log_domain_visits.find({}).sort({ "value":-1 }).limit(10).forEach(printjson);
MySQL中的等价物是:
drop table if exists NonFTP_Access_log_domain_visits;
create table NonFTP_Access_log_domain_visits (
`domain` varchar(255) NOT NULL,
`value` int unsigned not null,
PRIMARY KEY (`domain`),
KEY `value_index` (`value`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8
select domain, count(*) as value from NonFTP_Access_log group by domain;
select * from NonFTP_Access_log_domain_visits order by value desc limit 10;
好吧,MongoDB需要30个小时才能得到结果,MySQL需要20分钟读了一点之后,我得出结论,对于数据分析,我们将不得不使用Hadoop,因为MongoDB确实很慢。像这样的问题的答案是:
- MongoDB只使用线程
- Javascript太慢了
我做错了什么?这个结果正常吗?我应该使用Hadoop吗
我们正在以下环境中进行此测试:
- 操作系统:Suse Linux Enterprise Server 10(Xen上的虚拟服务器)
- RAM:10 Gb
- 核心:32(AMD Opteron处理器6128)
实际上我以前也回答过这个非常类似的问题。Map Reduce在MongoDB中的局限性之前已经概述过了——正如您所提到的,它是单线程的,必须转换为Java脚本(spidermonkey)和返回等。
这就是为什么还有其他选择:
- MongoDB Hadoop连接器(官方支持)
- 聚合框架(需要2.1+)
截至本文撰写之时,2.2.0的稳定版本尚未发布,但它已经发布到RC2,因此发布应该迫在眉睫。我建议尝试一下,作为这种类型测试的更有意义的比较。
显然,在聚合框架上使用group函数效果很好!:-)
下面的Javascript代码获取访问量最大的10个域,它们的访问量在17m17s中!
db.NonFTP_Access_log.aggregate(
{ $group: {
_id: "$domain",
visits: { $sum: 1 }
}},
{ $sort: { visits: -1 } },
{ $limit: 10 }
).result.forEach(printjson);
无论如何,我仍然不明白为什么MapReduce替代方案如此缓慢。我在MongoDB JIRA中打开了以下问题。
我认为您的结果很正常,并将尝试证明它们的合理性<。br>1.MySQL使用二进制格式,MongoDB使用JSON时对其进行了优化处理。因此,解析时间被添加到处理中。我估计它至少是10倍
2.JS确实比C慢得多。我认为至少可以假设系数为10。我们一起得到了大约x100——类似于你所看到的。20分钟x 1000是2000分钟或大约33小时
3.Hadoop在数据处理方面也不高效,但它能够使用所有的核心,这会有所不同。Java还对JIT进行了10多年的开发和优化
4.我建议不要看MySQL,而是看TPC-H基准Q1——这是纯粹的聚合。我认为像VectorWise这样的系统将显示每个核心的最大可能吞吐量