29

我有以下情况-

猪版使用 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 脚本,但是如何在 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?

干杯

4

11 回答 11

31

正如zjffdu所说,路径扩展是由shell完成的。解决问题的一种常见方法是简单地使用 Pig 参数(无论如何这是使脚本更可重复使用的好方法):

壳:

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

脚本.猪:

temp = LOAD '$input' USING SomeLoader() AS (...);
于 2010-09-24T18:07:41.197 回答
21

Pig 正在使用 hadoop 文件 glob 实用程序处理您的文件名模式,而不是 shell 的 glob 实用程序。Hadoop 记录在这里。如您所见,hadoop 不支持范围的 '..' 运算符。在我看来,您有两个选择 - 要么手动写出{date1,date2,date2,...,dateN}列表,如果这是一个罕见的用例,这可能是要走的路,或者编写一个为您生成该列表的包装脚本。从日期范围构建这样的列表对于您选择的脚本语言来说应该是一项微不足道的任务。对于我的应用程序,我使用了生成的列表路由,它工作正常(CHD3 分发)。

于 2011-02-16T15:57:10.000 回答
10

当我在尝试在脚本中创建文件 glob 并将其作为参数传递给 pig 脚本时遇到问题时,我遇到了这个答案。

当前的答案都不适用于我的情况,但我确实找到了一个可能在这里有用的一般答案。

就我而言,shell 扩展正在发生,然后将其传递到脚本中 - 导致 pig 解析器出现完全问题,这是可以理解的。

因此,只需将 glob 用双引号括起来,就可以保护它不被 shell 扩展,并将其按原样传递到命令中。

不会工作:

$ 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

我希望这可以减轻一些痛苦和痛苦。

于 2011-12-15T22:34:15.480 回答
6

因此,由于这有效:

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')
于 2013-02-14T22:21:34.067 回答
4

我发现这个问题是由 linux shell 引起的。Linux shell 将帮助您扩展

 {20100810..20100812} 

  20100810 20100811 20100812, 

然后你实际运行命令

bin/hadoop fs -ls 20100810 20100811 20100812

但是在 中hdfs api,它不会帮助您扩展表达式。

于 2010-09-15T10:12:44.460 回答
4

感谢戴夫坎贝尔。超出的一些答案是错误的,因为他们得到了一些选票。

以下是我的测试结果:

  • 作品

    • 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
于 2012-07-23T01:42:37.053 回答
4
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

如果变量位于文件路径的中间,则连接子文件夹名称或对所有文件使用“*”。

于 2011-07-24T13:35:48.050 回答
1

我是否需要使用 Python 等高级语言来捕获范围内的所有日期戳并将它们作为逗号分隔列表传递给 LOAD?

可能你不知道 - 这可以使用自定义加载 UDF 来完成,或者尝试重新考虑你的目录结构(如果你的范围大部分是静态的,这会很好用)。

另外:Pig 接受参数,也许这会对您有所帮助(也许您可以执行从一天开始加载数据并将其合并到结果集的功能,但我不知道是否可能)

编辑:可能编写简单的 python 或 bash 脚本来生成日期列表(文件夹)是最简单的解决方案,您只需将其传递给 Pig,这应该可以正常工作

于 2010-08-18T19:57:13.110 回答
1

对于 Romain 的回答,如果您只想参数化日期,shell 将像这样运行:

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

猪:

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

请注意引号。

于 2016-03-02T14:06:02.717 回答
0

Pig支持全球状态hdfs

所以我认为pig可以处理模式 /user/training/test/{20100810,20100811,20100812}

你能粘贴错误日志吗?

于 2010-08-20T06:14:10.543 回答
0

这是我用来生成日期列表的脚本,然后将此列表放入猪脚本参数中。非常棘手,但对我有用。

例如:

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

于 2020-06-27T00:34:52.963 回答