我的数据集大约有10亿个数据点。我想从中提取大约4600万个唯一数据点。
我想使用Hadoop来提取唯一值,但是在Hadoop上不断出现“Out of Memory”和Java堆大小错误 - 同时,我可以使用Python在一个盒子上轻松地运行它设置(哈希表,如果你愿意。)
我使用一个相当简单的算法来提取这些唯一值:我正在解析地图中的10亿行并输出如下所示的行:
UniqValueCount:I a
UniqValueCount:I a
UniqValueCount:I b
UniqValueCount:I c
UniqValueCount:I c
UniqValueCount:I d
然后运行“aggregate”reducer来获取结果,对于上面的数据集应如下所示:
I 4
这适用于一小组值,但是当我为10亿个数据点运行时(正如我所提到的,有4600万个键),作业失败了。
我在Amazon的Elastic Map Reduce上运行它,即使我使用6个m2.4xlarge节点(它们的最大内存节点各为68.4 GB),作业也会因“内存不足”错误而失败。
但我能够在一个m1.large(一个8 GB内存小得多的盒子)上使用带有Set数据结构(哈希表)的Python代码提取唯一值。我很困惑Hadoop的工作失败了,因为4600万独立不应该占用那么多的内存。
可能出现什么问题?我使用的是UniqValueCount吗?
答案 0 :(得分:2)
你可能在shuffle中遇到内存错误,请记住Hadoop在启动reducer之前对键进行排序。对于大多数应用程序来说,排序本身并不是必需的,但Hadoop使用它作为聚合属于键的所有值的方法。
对于您的示例,您的地图制作者最终会写入相同值的很多次,而您只关心给定键的唯一身份。以下是您现在正在做的事情:
Mapper output:
I -> a
I -> a
I -> a
I -> a
I -> b
I -> a
I -> b
Reducer input:
I -> [a, a, a, a, b, a, b]
Reducer output:
I -> 2
但是在这种情况下你真的不需要写5 * a或2 * b,因为你只关心uniques,所以1次就足够了。因此,除了计算reducer中的uniques外,您还可以通过确保只发送一次值来直接减少大量开销:
Mapper output:
I -> a
I -> b
Reducer input:
I -> [a, b]
Reducer output:
I -> 2
这样可以有效地减少网络带宽,并且随机分配的密钥会更少,因此随机播放将更加简单。
你可以这两种方式: