В этом вопросе есть несколько частей, связанных с запросами. Во-первых есть две схемы:Понимание производительности свиньи Apache
data = FOREACH source GENERATE
json#'id_str' AS post_id:chararray,
json#'user'#'id_str' AS user_id:chararray,
json#'created_at_str' AS tstamp_str:chararray,
FLATTEN(json#'entities'#'hashtags') AS hashtag:chararray;
stopwords = FOREACH another_source GENERATE
token AS stopword_hashtag:chararray;
stopwords
таблица содержит некоторые дубликаты и аннулирует, поэтому первое, что я сделал это
stopwords = FILTER stopwords BY stopword_hashtag IS NOT NULL;
stopwords = DISTINCT stopwords;
Тогда я хочу, чтобы отфильтровать stopwords
от хэштегов data
«s, так что я джойн с фильтром, а затем проекции назад data
:
joined = JOIN data BY hashtag LEFT, stopwords BY stopword_hashtag;
joined = FILTER joined BY stopwords::stopword_hashtag IS NULL;
data = FOREACH joined GENERATE
data::post_id AS post_id:chararray,
data::user_id AS user_id:chararray,
parse_time(data::tstamp_str) AS tstamp:long,
data::hashtag AS hashtag:chararray;
parse_time(char array)
- это Jython
UDF, который я написал для преобразования строки datetime в временную метку UNIX. После всего этого я сделаю группу + сортировку:
user_groups = FOREACH (GROUP data BY user_id) GENERATE
group AS user_id:chararray,
data.(hashtag, tstamp) AS time_series:bag{tuple:(tag:chararray,tstamp:long)};
user_groups = FOREACH user_groups {
sorted = ORDER time_series BY tstamp ASC;
GENERATE user_id, sorted;
}
Все они находятся в одном сценарии свиньи. У меня проблема с производительностью при выполнении этого процесса на больших данных. Я знаю, что это работает на маленьких примерах игрушек. Для больших примеров, где и data
, и stopwords
являются длинными, он занимает слишком много памяти и становится очень медленным.
Насколько я понимаю, я делаю фильтрацию как можно раньше, также делая только левое соединение. Любые предложения по оптимизации производительности?
Мое извинение за последнее обновление. Я пробовал подход @Ran Locar, который работает как шарм!
Существовал ошибка в Свиньи во время стадии фильтра:
output = FILTER data_with_count BY from_stopwords_count==0;
который сообщил
java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.Long
Потребовалось некоторое время, чтобы выяснить, обходной путь. Я решил ее в явном виде отливки как from_stopwords_count и от 0 до тех пор, то есть:
data_with_count = FOREACH data_with_count GENERATE
$0.., (long) from_stopwords_count AS from_stopwords_count:long;
output = FILTER data_with_count BY from_stopwords_count==0L;
Я предполагаю, что я мог бы отлиты как в целое, что, возможно, даст улучшение производительности, но я чувствую себя безопаснее с тех пор, учитывая размер из таблицы у меня есть.
Некоторые статистические данные моих входов:
- источник данных 1.1TB в формате GZIP
- источником игнорируемых слов является 400GB в формате GZIP, но я только принимая один столбец из него на самом деле.
Запрос выполняется в течение 2,3 часов, принимая 550 ГБ памяти и 180 вольт. Успешное завершение в конце, которое действительно спасло мой день!
не должно быть «левым внешним» соединением? По умолчанию левое будет означать внутреннее соединение, которое никогда не будет иметь никаких записей с 'stopwords :: stopword_hashtag IS NULL' – rahulbmv
@rahulbmv. Я думал, что левое соединение эквивалентно левому внешнему соединению. По крайней мере, так я думал о левом соединении в SQL. Позвольте мне вернуться и проверить документацию на свиньи. – Mai
@rahulbmv 'JOIN table BY col LEFT' является левым внешним соединением в Apache Pig в соответствии с 0.14.0 Doc (http://pig.apache.org/docs/r0.14.0/basic.html#join-outer) – Mai