web-dev-qa-db-ja.com

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>

上記のパスでわかるように、ディレクトリ名の1つは日付スタンプです。

問題: 20100810から20100813までの日付範囲からファイルをロードしたい。

日付範囲の「開始」と「終了」をパラメーターとしてPigスクリプトに渡すことができますが、LOADステートメントでこれらのパラメーターを使用するにはどうすればよいですか。私は次のことができます

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

以下はhadoopで動作します:

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

しかし、pigスクリプト内で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に渡す必要がありますか?

乾杯

29
Arnkrishn

Pigは、シェルのglobユーティリティではなく、hadoopファイルglobユーティリティを使用してファイル名パターンを処理しています。 Hadoopは文書化されていますここ。ご覧のとおり、hadoopは範囲の '..'演算子をサポートしていません。私には2つの選択肢があるようです-{date1,date2,date2,...,dateN}手動でリストを作成します。これがまれなユースケースである場合は、おそらくこの方法を使用するか、リストを生成するラッパースクリプトを作成します。日付範囲からこのようなリストを作成することは、選択したスクリプト言語にとって簡単な作業です。私のアプリケーションでは、生成されたリストルートを使用しましたが、正常に機能しています(CHD3ディストリビューション)。

21
Mark Tozzi

Zjffduが言ったように、パスの拡張はシェルによって行われます。問題を解決する一般的な方法の1つは、単にPigパラメーターを使用することです(とにかくスクリプトをより再開可能にする良い方法です)。

シェル:

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

script.pig:

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

スクリプトでファイルグロブを作成しようとして問題を抱えていたときにこの回答に出くわし、それをパラメーターとして豚スクリプトに渡しました。

現在の答えはどれも私の状況に当てはまりませんが、ここで役立つ一般的な答えを見つけました。

私の場合、シェルの拡張が行われ、それがスクリプトに渡されました-当然のことながら、ブタパーサーで完全な問題が発生しました。

そのため、グロブを二重引用符で囲むだけで、シェルによって展開されないように保護され、そのままコマンドに渡されます。

動作しない:

$ 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

これが誰かの苦痛と苦痛を救うことを願っています。

10
dave campbell

これが機能するので:

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')
6
Dexin Wang

デイブ・キャンベルに感謝します。彼らがいくつかの票を得たので、向こうの答えのいくつかは間違っています。

以下は私のテスト結果です。

  • 作品

    • 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
Javen Fang
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
balduran

この問題はLinux Shellが原因であることがわかりました。 Linux Shellはあなたの拡大を助けます

 {20100810..20100812} 

  20100810 20100811 20100812, 

その後、実際にコマンドを実行します

bin/hadoop fs -ls 20100810 20100811 20100812

しかし、hdfs api、式を展開するのに役立ちません。

4
zjffdu

Romainの答えに、日付をパラメーター化するだけの場合、シェルは次のように実行されます。

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

豚:

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

引用符に注意してください。

1
Datalicious

Pythonなどの上​​位言語を使用して、範囲内のすべての日付スタンプをキャプチャし、コンマ区切りリストとしてLOADに渡す必要がありますか?

おそらくそうではありません-これは、カスタムLoad UDFを使用して実行するか、ディレクトリ構造を再検討してみてください(これは、範囲がほとんど静的な場合に有効です)。

さらに:Pigはパラメーターを受け入れます。これはおそらく役立つでしょう(おそらく、1日からデータをロードして結果セットに結合する機能を実行できますが、可能かどうかはわかりません)。

編集:おそらくシンプルなpythonまたは日付のリスト(フォルダー)を生成するbashスクリプトを記述するのが最も簡単な解決策です。単にPigに渡す必要があります。

1
wlk

Pighdfsのグローブステータスをサポートします。

pigはパターン/user/training/test/{20100810,20100811,20100812}を処理できると思います。

エラーログを貼り付けていただけますか?

0
zjffdu