将行值聚合到列中

时间:2013-11-21 07:21:14

标签: hadoop apache-pig

我有这样的数据:

2013-11    localhost       kern
2013-11    localhost       kern
2013-11    192.168.0.59    daemon
2013-12    localhost       kern
2013-12    localhost       daemon
2013-12    localhost       mail

你明白了。我正在尝试按日期对上面进行分组(作为行键),并且有一列对应于每个kerndaemon等的计数。简而言之,我想要的输出应该是下面:

-- date, count(kern), count(daemon), count(mail)
(2013-11, 2, 1, 0)
(2013-12, 1, 1, 1)

目前,我的方法是这样的。

valid_records = FILTER formatted_records BY date is not null;

date_group = GROUP valid_records BY date;
facilities = FOREACH date_group {
    -- DUMB way to filter for now :(
    kern = FILTER valid_records BY facility == 'kern';
    user = FILTER valid_records BY facility == 'user';
    daemon = FILTER valid_records BY facility == 'daemon';

    -- this need to be in order so it get mapped correctly to HBase
    GENERATE group, COUNT(kern), COUNT(user), COUNT(daemon);
}

两个问题:

  1. 我上面有3个过滤器,但在生产中,应该有超过10个过滤器。如果我使用上面的很多FILTER,是否会有任何性能影响?

  2. 还有其他更好的方法吗?

2 个答案:

答案 0 :(得分:1)

我认为您的问题是您正在寻找具有浮动模式的输出。但似乎您所要做的就是按复合键分组: 用这个脚本:

formatted_records = LOAD 'input' AS (date: chararray, host: chararray, facility: chararray);
valid_records = FILTER formatted_records BY date is not null;
counts = FOREACH (GROUP valid_records BY (date, facility)) GENERATE
        group.date AS date,
        group.facility AS facility,
        COUNT(valid_records) AS the_count;
DUMP counts;

你会得到:

(2013-11,kern,2)
(2013-11,daemon,1)
(2013-12,kern,1)
(2013-12,mail,1)
(2013-12,daemon,1)

给出了相同的信息。

如果你想像你那样花哨地格式化输出,那么最好分别使用通用语言(如Java或Python)来完成这些任务(假设Pig的输出足够小以适应内存) 。猪并不擅长这个。

答案 1 :(得分:0)

只要你有一个群组操作,你就会有一个减少阶段,这意味着你很可能有编写临时映射器输出,二次排序等的开销。还有其他猪操作员会触发减少阶段,但我认为FILTER不是其中之一:映射器任务可以过滤输入并创建多个输出,然后将其排序并发送到单个减少阶段。

换句话说,在猪身上看起来很混乱的东西实际上可以非常高效,看起来简洁的东西可以产生比你想象的更多的地图减少开销。

如果从命令行运行pig作业,您将看到正在使用的运算符的摘要以及逻辑计划产生的M / R作业列表。