Подтвердить что ты не робот

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

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

Используется версия для свиней 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.

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

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

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

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

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

Журнал ошибок:

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 как список, разделенный запятой?

веселит

4b9b3361

Ответ 1

Свинья обрабатывает ваш шаблон имени файла, используя утилиты glo файла для файлов cookie, а не утилиты glob-оболочки. Hadoop документированы здесь. Как вы можете видеть, hasoop не поддерживает оператор ".." для диапазона. Мне кажется, у вас есть два варианта: либо выпишите список {date1,date2,date2,...,dateN} вручную, который, если это редкий вариант использования, вероятно, подходит, или напишите обертку script, которая генерирует этот список для вас. Создание такого списка из диапазона дат должно быть тривиальной задачей для языка сценариев по вашему выбору. Для моего приложения я пошел с созданным списком маршрутов, и он отлично работает (дистрибутив CHD3).

Ответ 2

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

оболочки:

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

script.pig:

temp = LOAD '$input' USING SomeLoader() AS (...);

Ответ 3

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

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

в моем случае разрастание оболочки происходило, а затем передавалось в script, что вызывало полные проблемы с парсером свиньи, понятно.

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

НЕ РАБОТАЕТ:

$ 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

Надеюсь, это избавит кого-то от боли и агонии.

Ответ 4

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

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

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

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

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

Скажите, что вы хотите загрузить данные с 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')

Ответ 5

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

 {20100810..20100812} 

к

  20100810 20100811 20100812, 

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

bin/hadoop fs -ls 20100810 20100811 20100812

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

Ответ 6

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

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

Ответ 7

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

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

  • Работа

    • 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

Ответ 8

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

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

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

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

Ответ 9

Чтобы ответить Romain, если вы хотите просто параметризовать дату, оболочка будет работать следующим образом:

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

свинья:

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

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

Ответ 10

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

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

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