我关注帮助How to handle spill memory in pig来自 alexeipab,它确实工作正常,但我现在有另一个问题,相同的示例代码:
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,这将与不加盐计算的结果有很大不同。
有什么解决办法吗?如果先过滤,会消耗很多 JOIN 作业,并降低性能。
最佳答案
为此,您需要在 mid_set.yyy 和 salt 之间建立多对一关系,以便来自不同行的 mid_set.yyy 的相同值映射到相同的 salt 值。如果不是,那么 mid_set.yyy 的值将出现在 GROUP pymt BY (key, salt) 生成的不同包中,在不同的盐中存活 DISTINCT,因此在最终汇总中多次包含。这就是为什么在使用 salt 和 DISTINCT 的 COUNT 时会得到错误的结果。
一种简单的方法是用 mid_set.yyy 本身替换 salt 或编写一个 UDF/静态方法,该方法通过对 mid_set.yyy 进行散列计算 salt 并执行 mod N,其中 N 可以是 1 到无穷大,以获得最佳分布N应该是质数。
关于hadoop - 如何用盐处理 DISTINCT,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12087690/