Переносить поля с собой или хранить и присоединять?

В Hadoop, использующем Pig, у меня есть большое количество полей в нескольких отдельных источниках, которые я загружаю, фильтрую, проецирую, группирую, запускаю через пару пользовательских функций Java, объединяю, проецирую и сохраняю. (Это повседневная жизнь в Hadoop.) Некоторые поля исходной загрузки данных не используются UDF и не нужны до окончательного сохранения.

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

Тривиальный игрушечный пример — источник данных со столбцами name,weight,height, и в конечном итоге я хочу сохранить name,weight,heightSquared. Мой UDF будет возводить высоту за меня. Как лучше:

inputdata = LOAD 'data' AS name,weight,height;
outputdata = FOREACH inputdata
                GENERATE myudf.squareHeight(name,weight,height)
                AS (name,weight,heightSquared);
STORE outputdata INTO 'output';

or

inputdata = LOAD 'data' AS name,weight,height;
name_weight = FOREACH inputdata
                GENERATE name,weight;
intdata1 = FOREACH inputdata
                GENERATE myudf.squareHeight(name,height)
                AS (iname,heightSquared);
intdata2 = JOIN intdata1 BY iname, name_weight BY name;
outputdata = FOREACH intdata2
                GENERATE name,weight,heightSquared;
STORE outputdata INTO 'output';

В данном случае это выглядит довольно очевидно: первый случай лучше. Но UDF должна читать, сохранять и выводить поле weight. Когда у вас есть 15 полей, на которые UDF не обращает внимания, и только одно, то первый случай все же лучше?


person Jeff Snider    schedule 05.02.2014    source источник


Ответы (1)


Если у вас есть 15 полей, которые не нужны UDF, не отправляйте их в UDF. В вашем примере нет причин писать UDF для трех полей, если он будет использовать только третье. Лучшим сценарием для вашего примера будет

inputdata = LOAD 'data' AS name,weight,height;
outputdata =
    FOREACH inputdata
    GENERATE
        name,
        weight,
        myudf.squareHeight(height) AS heightSquared;
STORE outputdata INTO 'output';

Итак, это относится к случаю UDF. Если у вас есть куча полей, которые вы хотите сохранить, но вы не собираетесь использовать их ни в одном из следующих нескольких циклов уменьшения карты, вы можете сохранить их немедленно, а затем снова соединить. было бы вопросом эмпирической проверки того, какой подход быстрее для вашего конкретного случая.

person reo katoa    schedule 05.02.2014
comment
Это довольно хороший ответ на вопрос, который я задал. (Я не уверен, как применить это к моей фактической ситуации, когда я передаю пакеты данных кортежей в UDF и получаю взамен набор данных кортежей. Я задам это как отдельный вопрос. ) - person Jeff Snider; 06.02.2014
comment
Кроме того, вы потратили время на написание хорошего ответа, но не проголосовали за вопрос. Что мешает этому голосовать? - person Jeff Snider; 06.02.2014
comment
Мешки кортежей ничем не отличаются. Вы можете использовать оператор проецирования, чтобы сократить свои сумки только до тех полей, которые интересны. Вместо отправки person в UDF с тремя полями просто отправьте person.height. Теперь UDF получает пакет, кортежи которого содержат только одно поле. Между прочим, я не уверен, что передача слишком большого количества данных в UDF является проблемой производительности в той же степени, что и проблема удобства обслуживания. Производительность вступает в игру только в том случае, если у вас есть несколько циклов MR, как я упоминал во второй половине ответа. Что касается голосов, я просто не склонен голосовать за вопросы, вот и все. - person reo katoa; 06.02.2014
comment
Я не смог применить то, что вы написали в комментарии выше, к моей проблеме. Я задал конкретный вопрос здесь: > stackoverflow.com/questions/21711584/ - person Jeff Snider; 11.02.2014