Как мне «перегруппировать» отношения свиньи? - PullRequest
1 голос
/ 29 сентября 2011

Предположим, у меня есть входной файл 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 на "other" и перегруппируйте. Наконец, UNION, что в результате вместе с above_threshold, а затем снова запустите окончательный прогноз.
  2. Или точно следовать исходному сценарию, но при создании projection сгенерировать a условно (на основе SUM(sources.b)), затем повторно сгруппировать projection (чтобы сгруппировать все «другие» строки вместе) и затем спроецируйте снова (чтобы сгладить перегруппированные данные).

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

1 Ответ

1 голос
/ 01 октября 2011

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

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

  • Счет below_threshold будет довольно быстрым, потому что вам нужен только один редуктор, а объединитель будет творить чудеса только одним ключом.
  • В зависимости от вашего приложения вам не нужно до 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;
...