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.

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

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

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

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

Но это не удается, когда я пытаюсь сделать то же самое с LOAD внутри скрипта свиньи. Как использовать параметры, переданные скрипту 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 в виде списка, разделенного запятыми?

ваше здоровье


person Arnkrishn    schedule 18.08.2010    source источник
comment
Для людей, которые нашли этот пост при поиске ОШИБКА 1066: невозможно открыть итератор для псевдонима вот общее решение.   -  person Dennis Jaheruddin    schedule 28.12.2015


Ответы (11)


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

person Mark Tozzi    schedule 16.02.2011
comment
обновление ссылки hadoop.apache.org/docs/stable/api/org/apache/hadoop/fs/ - person BozoJoe; 20.06.2013

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

оболочка:

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

скрипт.свинья:

temp = LOAD '$input' USING SomeLoader() AS (...);
person Romain    schedule 24.09.2010
comment
Это вообще не работает, но может показаться, что работает, потому что у pig ужасная обработка командной строки. Вы используете bash для создания командной строки, которая будет вызывать pig. Но он расширяется до pig -f script.pig -param input=/user/training/test/20100810 input=/user/training/test/20100811 input=/user/training/test/20100812 (измените pig на echo, если хотите). Только первому input= предшествует -param; остальные вообще не являются привязками параметров свиньи. Но свинья просто перестает обрабатывать аргументы командной строки при первом нераспознанном input=... и запускает только первое свидание! - person Ben; 30.08.2016
comment
Вы можете доказать, что свинка игнорирует все после второго input=..., используя скрипт свиньи со вторым параметром (скажем, output) и поставив -param output=... после входной привязки. Вы получаете сообщение об ошибке Undefined parameter : output. - person Ben; 30.08.2016

я наткнулся на этот ответ, когда у меня возникли проблемы с попыткой создать файл 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

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

person dave campbell    schedule 15.12.2011

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

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')
person Dexin Wang    schedule 14.02.2013
comment
подстановочный знак в синтаксисе фигурных скобок, например. /test/{201210*, 201211*} очень эффективен и прост в реализации. - person Quetzalcoatl; 05.06.2017

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

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

person balduran    schedule 24.07.2011

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

 {20100810..20100812} 

to

  20100810 20100811 20100812, 

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

bin/hadoop fs -ls 20100810 20100811 20100812

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

person zjffdu    schedule 15.09.2010

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

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

  • Работает

    • pig -f test.pig -param input="/test_{20120713,20120714}.txt"
      • Cannot have space before or after "," in the expression
    • 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
      • Cannot have space before or after "," in the expression
  • Не работает

    • 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
person Javen Fang    schedule 23.07.2012

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

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

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

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

person wlk    schedule 18.08.2010
comment
Спасибо Войтек. Что ж, сетка уже на месте, и изменить структуру каталогов невозможно. Я вижу это, temp = LOAD '/user/training/test/{20100810,20100811,20100812}' USING SomeLoader() AS (...); и hadoop fs -ls /user/training/test/{20100810,20100811,20100812} работает нормально. hadoop fs -ls /user/training/test/{20100810..20100812} также работает, но temp = LOAD '/user/training/test/{20100810..20100812}' USING SomeLoader() AS (...); происходит сбой при температуре дампа или температуре хранения. - person Arnkrishn; 19.08.2010

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

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

свинья:

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

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

person Datalicious    schedule 02.03.2016

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

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

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

person zjffdu    schedule 20.08.2010
comment
Привет, zjffdu, я скопировал журнал ошибок в вопрос. Спасибо - person Arnkrishn; 26.08.2010

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

Например:

DT=20180101
DT_LIST=''
for ((i=0; i<=$DAYS; i++))
do
    d=$(date +%Y%m%d -d "${DT} +$i days");
    DT_LIST=${DT_LIST}$d','
done

size=${#DT_LIST}
DT_LIST=${DT_LIST:0:size-1}


pig -p input_data=xxx/yyy/'${DT_LIST}' script.pig

person moonshang    schedule 27.06.2020