2016-03-05 3 views
1

В этом вопросе есть несколько частей, связанных с запросами. Во-первых есть две схемы:Понимание производительности свиньи 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. источник данных 1.1TB в формате GZIP
  2. источником игнорируемых слов является 400GB в формате GZIP, но я только принимая один столбец из него на самом деле.

Запрос выполняется в течение 2,3 часов, принимая 550 ГБ памяти и 180 вольт. Успешное завершение в конце, которое действительно спасло мой день!

+0

не должно быть «левым внешним» соединением? По умолчанию левое будет означать внутреннее соединение, которое никогда не будет иметь никаких записей с 'stopwords :: stopword_hashtag IS NULL' – rahulbmv

+0

@rahulbmv. Я думал, что левое соединение эквивалентно левому внешнему соединению. По крайней мере, так я думал о левом соединении в SQL. Позвольте мне вернуться и проверить документацию на свиньи. – Mai

+0

@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

ответ

2

Существует способ избежать соединения между секундомерами и данными в целом. По существу, вам необходимо:

  • Нет необходимости в DISTINCT или фильтрации стоп-слов.
  • получить данные и игнорируемых слов в одну и ту же схему

    stopwords = FOREACH another_source GENERATE 
    '' as post_id, 
    '' as user_id, 
    '' as tstamp_str, 
    token AS hashtag:chararray, 
    0 as from_data, 
    1 as from_stopwords; 
    
  • добавить from_data и from_stopwords поля в схеме данных

    data = FOREACH data GENERATE 
    $0.., 
    1 as from_data, 
    0 as from_stopwords; 
    
  • UNION два отношения

    data_with_stopwords = UNION data, stopwords; 
    
  • группа маркером. В каждой группе у вас будут строки из обоих отношений.

    data_with_stopwords_and_counts = foreach (group data_with_stopwords by hashtag) generate 
    $0.., SUM(data_with_stopwords.from_data) as from_data_sum, SUM(data_with_stopwords.from_stopwords) as from_stopwords_sum; 
    

каждая строка теперь будет иметь ключ группы, все строки, принадлежащие к группе, и два числа. Вам нужны только строки, где from_stopwords_sum == 0, так как эти строки не отображаются в списке стоп-слов (поэтому вам больше не нужен DISTINCT ... вы не возражаете, чтобы слова были в словах остановки более одного раза; вы просто получите from_stopwords_sum> = 1, и игнорировать эту строку)

  • фильтр по from_stopwords_sum == 0 и придавить список

    data_with_stopwords_and_counts = foreach (filter data_with_stopwords_and_counts by from_stopwords_sum==0) generate 
    flatten($1); 
    

Этот подход заменяет РЕГИСТРИРУЙТЕСЬ группой ОТ. Когда я тестировал его на многих многих ГБ данных, он закончил в < 10 минут по сравнению с несколькими часами, используя соединения. В конце ваших строк будут добавлены дополнительные поля сумм, но вы можете их удалить позже.

+0

Позвольте мне попробовать мой набор данных сегодня днем ​​и сообщить об улучшении производительности в моем случае. Но в любом случае я думаю, что это гениально! – Mai

+0

См. Обновление вопроса – Mai

+0

Некоторые вопросы, которые у меня есть для вас, если вы любезно дадите мне подсказки: каково обоснование вашего запроса? Почему это быстрее и эффективнее? Что вы прочитали, чтобы получить эту часть знаний? Я хотел бы стать таким же хорошим, как и вы! – Mai

Смежные вопросы