如何用盐处理DISTINCT

时间:2012-08-23 08:31:37

标签: hadoop apache-pig

我从alexeipab那里得到了帮助How to handle spill memory in pig,它确实很好用,但我现在有另一个问题,相同的示例代码:

pymt = LOAD 'pymt' USING PigStorage('|') AS ($pymt_schema);

pymt_grp_with_salt = GROUP pymt BY (key,salt)

results_with_salt = FOREACH pymt_grp {
    --distinct
    mid_set = FILTER pymt BY xxx=='abc';
    mid_set_result = DISTINCT mid_set.yyy;
    result = COUNT(mid_set_result)   
}

pymt_grp = GROUP results_with_salt BY key;

result = FOREACH pymt_grp {

   GENERATE SUM(results_with_salt.result); --it is WRONG!!
}

我不能在该组中使用sum,它与不使用salt计算的结果非常不同。

有什么解决方案吗?如果先过滤,则会花费很多JOIN作业,并降低性能。

2 个答案:

答案 0 :(得分:1)

为了实现这一点,你需要在mid_set.yyy和salt之间建立多对一的关系,这样来自不同行的mid_set.yyy的相同值将被映射到相同的salt值。如果不是,那么mid_set.yyy的值将出现在GROUP pymt BY(key,salt)生成的不同包中,在不同的盐中存活DISTINCT,因此在最终汇总中包含多次。这就是为什么在使用salt和COUNT的DISTINCT时可能会得到错误的结果。

一种简单的方法可以是用mid_set.yyy本身替换salt,或者编写一个UDF /静态方法,通过获取mid_set.yyy的哈希来计算salt,并执行mod N,其中N可以是1到无穷大,以获得最佳分布N应该是素数。

答案 1 :(得分:0)

感谢alexeipab,你给我一个很大的帮助,我的工作如下

pymt = LOAD 'pymt' USING PigStorage('|') AS ($pymt_schema);

pymt = FOREACH pymt GENERATE *, (yyy%$prime_num) as salt;

pymt_grp_with_salt = GROUP pymt BY (key,salt);

它有效!!

如果yyy是num integer,则可以使用hash将字符串或其他字符串转换为整数