Как перегруппировать отношение свиньи?

Предположим, у меня есть входной файл input.dat, который выглядит так:

apples 10
oranges 30
apples 6
pears 5

Теперь, когда я загружаю, группирую и проецирую данные:

sources = LOAD 'input.dat' as { a:chararray, b:int };
grouped = GROUP sources BY a;
projection = foreach sources generate flatten(group), SUM(sources.b);
dump projection;

Я получаю следующее:

apples 16
oranges 30
pears 5

Теперь я хочу «перегруппировать» данные, где SUM(sources.b) ниже некоторого порога, в одну строку. Например, если бы порог был равен 20, я бы получил:

other 21
oranges 30

потому что сумма как для «яблок», так и для «груш» была ниже порога 20.

Мне кажется, что я могу следовать нескольким различным подходам:

  1. Используйте оператор SPLIT для grouped, чтобы создать два отношения: above_threshold и below_threshold. Затем спроектируйте below_threshold, чтобы заменить значение a на «другое» и перегруппируйте. Наконец, UNION результат вместе с above_threshold, а затем снова запустите окончательную проекцию.
  2. Или точно следуйте исходному сценарию, но при создании projection сгенерируйте a условно (на основе SUM(sources.b)), затем перегруппируйте projection (чтобы сгруппировать все «другие» строки вместе), а затем снова спроецируйте (чтобы сгладить повторные строки). сгруппированные данные).

Является ли один из вышеперечисленных подходов явно лучше другого? Или есть другой подход, который будет более эффективным или простым в обслуживании?


person Chris Phillips    schedule 29.09.2011    source источник


Ответы (1)


Вариант 1 лучше. Это связано с тем, что вариант 1 должен передавать только below_threshold данных в счетчик записей M/R; а в варианте 2 вы все перегруппировываете вроде как.

Кроме того, в подходе 1 есть несколько хороших моментов, в первую очередь:

  • Подсчет below_threshold будет довольно быстрым, потому что вам нужен только 1 редьюсер, а объединитель будет творить чудеса только с одним ключом.
  • В зависимости от вашего приложения вам не нужно UNION. Вы можете просто вывести в два места, а затем «объединить», рассматривая их как один и тот же вывод из свиньи. Например, вы все еще можете сделать hadoop fs -getmerge my_out/*/part-r-* output, чтобы захватить оба выхода.

Итак, я вижу, что ваш скрипт Pig выглядит так:

sources = LOAD 'input.dat' as { a:chararray, b:int };
grouped = GROUP sources BY a;
projection = foreach sources generate flatten(group) as n, SUM(sources.b) as s;
SPLIT projection into above_threshold if s >= 20, below_threshold if s < 20;
dump above_threshold;

below_grouped = GROUP below_threshold BY 'other' PARALLEL 1;
below_projection = FOREACH below_grouped GENERATE group, SUM(below_threshold.s);
dump below_projection;
person Donald Miner    schedule 01.10.2011