Pig Latin: загрузка нескольких файлов из диапазона дат (часть структуры каталогов) - PullRequest
29 голосов
/ 18 августа 2010

У меня есть следующий сценарий:

Используемая версия Pig 0.70

Пример структуры каталогов HDFS:

/user/training/test/20100810/<data files>
/user/training/test/20100811/<data files>
/user/training/test/20100812/<data files>
/user/training/test/20100813/<data files>
/user/training/test/20100814/<data files>

Как видно из приведенных выше путей, одиниз имен каталогов есть отметка даты.

Проблема: Я хочу загрузить файлы из диапазона дат, скажем, с 20100810 по 20100813.

Я могу передать 'из'и' до 'диапазона дат в качестве параметров скрипта Pig, но как мне использовать эти параметры в операторе LOAD.Я могу сделать следующее

temp = LOAD '/user/training/test/{20100810,20100811,20100812}' USING SomeLoader() AS (...);

Следующее работает с hadoop:

hadoop fs -ls /user/training/test/{20100810..20100813}

Но происходит сбой, когда я пытаюсь сделать то же самое с LOAD внутри скрипта pig.Как использовать параметры, переданные в сценарий Pig, для загрузки данных из диапазона дат?

Журнал ошибок следует:

Backend error message during job submission
-------------------------------------------
org.apache.pig.backend.executionengine.ExecException: ERROR 2118: Unable to create input splits for: hdfs://<ServerName>.com/user/training/test/{20100810..20100813}
        at org.apache.pig.backend.hadoop.executionengine.mapReduceLayer.PigInputFormat.getSplits(PigInputFormat.java:269)
        at org.apache.hadoop.mapred.JobClient.writeNewSplits(JobClient.java:858)
        at org.apache.hadoop.mapred.JobClient.writeSplits(JobClient.java:875)
        at org.apache.hadoop.mapred.JobClient.access$500(JobClient.java:170)
        at org.apache.hadoop.mapred.JobClient$2.run(JobClient.java:793)
        at org.apache.hadoop.mapred.JobClient$2.run(JobClient.java:752)
        at java.security.AccessController.doPrivileged(Native Method)
        at javax.security.auth.Subject.doAs(Subject.java:396)
        at org.apache.hadoop.security.UserGroupInformation.doAs(UserGroupInformation.java:1062)
        at org.apache.hadoop.mapred.JobClient.submitJobInternal(JobClient.java:752)
        at org.apache.hadoop.mapred.JobClient.submitJob(JobClient.java:726)
        at org.apache.hadoop.mapred.jobcontrol.Job.submit(Job.java:378)
        at org.apache.hadoop.mapred.jobcontrol.JobControl.startReadyJobs(JobControl.java:247)
        at org.apache.hadoop.mapred.jobcontrol.JobControl.run(JobControl.java:279)
        at java.lang.Thread.run(Thread.java:619)
Caused by: org.apache.hadoop.mapreduce.lib.input.InvalidInputException: Input Pattern hdfs://<ServerName>.com/user/training/test/{20100810..20100813} matches 0 files
        at org.apache.hadoop.mapreduce.lib.input.FileInputFormat.listStatus(FileInputFormat.java:231)
        at org.apache.pig.backend.hadoop.executionengine.mapReduceLayer.PigTextInputFormat.listStatus(PigTextInputFormat.java:36)
        at org.apache.hadoop.mapreduce.lib.input.FileInputFormat.getSplits(FileInputFormat.java:248)
        at org.apache.pig.backend.hadoop.executionengine.mapReduceLayer.PigInputFormat.getSplits(PigInputFormat.java:258)
        ... 14 more



Pig Stack Trace
---------------
ERROR 2997: Unable to recreate exception from backend error: org.apache.pig.backend.executionengine.ExecException: ERROR 2118: Unable to create input splits for: hdfs://<ServerName>.com/user/training/test/{20100810..20100813}

org.apache.pig.impl.logicalLayer.FrontendException: ERROR 1066: Unable to open iterator for alias test
        at org.apache.pig.PigServer.openIterator(PigServer.java:521)
        at org.apache.pig.tools.grunt.GruntParser.processDump(GruntParser.java:544)
        at org.apache.pig.tools.pigscript.parser.PigScriptParser.parse(PigScriptParser.java:241)
        at org.apache.pig.tools.grunt.GruntParser.parseStopOnError(GruntParser.java:162)
        at org.apache.pig.tools.grunt.GruntParser.parseStopOnError(GruntParser.java:138)
        at org.apache.pig.tools.grunt.Grunt.run(Grunt.java:75)
        at org.apache.pig.Main.main(Main.java:357)
Caused by: org.apache.pig.backend.executionengine.ExecException: ERROR 2997: Unable to recreate exception from backend error: org.apache.pig.backend.executionengine.ExecException: ERROR 2118: Unable to create input splits for: hdfs://<ServerName>.com/user/training/test/{20100810..20100813}
        at org.apache.pig.backend.hadoop.executionengine.mapReduceLayer.Launcher.getStats(Launcher.java:169)

Нужно ли использовать более высокий язык, такой как Python, для захвата всех отметок даты в диапазоне и передачи их в LOAD в виде списка через запятую?

ура

Ответы [ 10 ]

31 голосов
/ 24 сентября 2010

Как сказал zjffdu, расширение пути выполняется оболочкой.Один из распространенных способов решения вашей проблемы - это просто использовать параметры Pig (в любом случае это хороший способ сделать ваш сценарий более возобновляемым):

shell:

pig -f script.pig -param input=/user/training/test/{20100810..20100812}

script.pig:

temp = LOAD '$input' USING SomeLoader() AS (...);
21 голосов
/ 16 февраля 2011

Pig обрабатывает ваш шаблон имени файла с помощью утилит glob файла hadoop, а не утилит glob оболочки.Hadoop документированы здесь .Как видите, hadoop не поддерживает оператор «..» для диапазона.Мне кажется, у вас есть два варианта - либо выписать список {date1,date2,date2,...,dateN} от руки, что, если это редкий случай использования, вероятно, лучше, или написать скрипт-обертку, который генерирует этот список для вас.Создание такого списка из диапазона дат должно быть тривиальной задачей для языка сценариев по вашему выбору.Для моего приложения я выбрал маршрут сгенерированного списка, и он работает нормально (распределение CHD3).

10 голосов
/ 16 декабря 2011

Я столкнулся с этим ответом, когда у меня возникли проблемы при попытке создать глобус файла в скрипте, а затем передать его в качестве параметра в скрипт PIG.

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

в моем случае происходило расширение оболочки, которое затем передавалось в сценарий, что, по понятным причинам, вызывало полные проблемы с анализатором pig *. 1005 *

поэтому простое окружение глобуса двойными кавычками защищает его от раскрытия оболочкой и передает его в команду как есть.

НЕ РАБОТАЕТ:

$ pig -f my-pig-file.pig -p INPUTFILEMASK='/logs/file{01,02,06}.log' -p OTHERPARAM=6

БУДЕТ РАБОТАТЬ

$ pig -f my-pig-file.pig -p INPUTFILEMASK="/logs/file{01,02,06}.log" -p OTHERPARAM=6

Надеюсь, это спасет кого-то от боли и мучений.

6 голосов
/ 15 февраля 2013

Так как это работает:

temp = LOAD '/user/training/test/{20100810,20100811,20100812}' USING SomeLoader()

, но это не работает:

temp = LOAD '/user/training/test/{20100810..20100812}' USING SomeLoader()

, но если вы хотите, чтобы диапазон дат охватывал 300 дней и передавал полный списокЗАГРУЗКА не элегантна, мягко говоря.Я придумал это, и это работает.

Скажем, вы хотите загрузить данные с 2012-10-08 по сегодняшний день 2013-02-14, то, что вы можете сделать, это

temp = LOAD '/user/training/test/{201210*,201211*,201212,2013*}' USING SomeLoader()

затемсделать фильтр после этого

filtered = FILTER temp BY (the_date>='2012-10-08')
4 голосов
/ 23 июля 2012

Благодаря Дэйву Кэмпбеллу. Некоторые из ответов за пределами являются неправильными, так как они получили несколько голосов.

Ниже приведен мой результат теста:

  • Работает

    • pig -f test.pig -param input="/test_{20120713,20120714}.txt"
      • Не может быть пробела до или после "," в выражении
    • pig -f test.pig -param input="/test_201207*.txt"
    • pig -f test.pig -param input="/test_2012071?.txt"
    • pig -f test.pig -param input="/test_20120713.txt,/test_20120714.txt"
    • pig -f test.pig -param input=/test_20120713.txt,/test_20120714.txt
      • Не может быть пробела до или после "," в выражении
  • не работает

    • pig -f test.pig -param input="/test_{20120713..20120714}.txt"
    • pig -f test.pig -param input=/test_{20120713,20120714}.txt
    • pig -f test.pig -param input=/test_{20120713..20120714}.txt
4 голосов
/ 24 июля 2011
temp = LOAD '/user/training/test/2010081*/*' USING SomeLoader() AS (...);
load 20100810~20100819 data
temp = LOAD '/user/training/test/2010081{0,1,2}/*' USING SomeLoader() AS (...);
load 20100810~2010812 data

если переменная находится в середине пути к файлу, объедините имя подпапки или используйте '*' для всех файлов.

4 голосов
/ 15 сентября 2010

Я обнаружил, что эта проблема вызвана оболочкой Linux. Оболочка Linux поможет вам расширить

 {20100810..20100812} 

до

  20100810 20100811 20100812, 

тогда вы фактически запускаете команду

bin/hadoop fs -ls 20100810 20100811 20100812

Но в hdfs api это не поможет вам расширить выражение.

1 голос
/ 02 марта 2016

К ответу Ромена, если вы хотите просто параметризовать дату, оболочка будет работать так:

pig -param input="$(echo {20100810..20100812} | tr ' ' ,)" -f script.pig

pig:

temp = LOAD '/user/training/test/{$input}' USING SomeLoader() AS (...);

Обратите внимание на кавычки.

1 голос
/ 18 августа 2010

Нужно ли использовать более высокий язык, такой как Python, для захвата всех отметок даты в диапазоне и передачи их в LOAD в виде списка через запятую?

Возможно, вы этого не сделаете - это можно сделать с помощью пользовательского Load UDF или попробуйте переосмыслить структуру каталогов (это будет хорошо работать, если ваши диапазоны в основном статичны).

дополнительно: Pig принимает параметры, может быть, это поможет вам (возможно, вы могли бы сделать функцию, которая будет загружать данные за один день и объединять их в результирующий набор, но я не знаю, возможно ли это)

edit: возможно, написание простого скрипта на python или bash, который генерирует список дат (папок), является самым простым решением, вам нужно просто передать его в Pig, и это должно нормально работать

0 голосов
/ 20 августа 2010

Pig поддержка статуса глобуса hdfs,

, поэтому я думаю, pig может обработать шаблон /user/training/test/{20100810,20100811,20100812},

Не могли бы вы вставить журналы ошибок?

...