3

私は最近私の仕事でこの問題に遭遇しました、それは豚が平らになることについてです。簡単な例を使って表現します

2つのファイル
===file1===
1_a
2_b
4_d

=== file2(タブ区切り)===
1 a
2 b
3 c

豚のスクリプト1:

a = load 'file1' as (str:chararray);
b = load 'file2' as (num:int, ch:chararray);
a1 = foreach a generate flatten(STRSPLIT(str,'_',2)) as (num:int, ch:chararray);
c = join a1 by num, b by num;
dump c;   -- exception java.lang.String cannot be cast to java.lang.Integer

豚のスクリプト2:

a = load 'file1' as (str:chararray);
b = load 'file2' as (num:int, ch:chararray);
a1 = foreach a generate flatten(STRSPLIT(str,'_',2)) as (num:int, ch:chararray);
a2 = foreach a1 generate (int)num as num, ch as ch;
c = join a2 by num, b by num;
dump c;   -- exception java.lang.String cannot be cast to java.lang.Integer

豚のスクリプト3:

a = load 'file1' as (str:chararray);
b = load 'file2' as (num:int, ch:chararray);
a1 = foreach a generate flatten(STRSPLIT(str,'_',2));
a2 = foreach a1 generate (int)$0 as num, $1 as ch;
c = join a2 by num, b by num;
dump c;   -- right

スクリプト1、2が間違っていて、スクリプト3が正しい理由がわかりません。また、関係c、thxを取得するためのより簡潔な式があることも知りたいです。

4

1 に答える 1

4

PigStorageを使用していない特別な理由はありますか?それはあなたの生活をとても楽にすることができるからです:)。

a = load '/file1' USING PigStorage('_') AS (num:int, char:chararray);
b = load '/file2' USING PigStorage('\t') AS (num:int, char:chararray);
c = join a by num, b by num;
dump c;

また、file1では区切り文字としてアンダースコアを使用しましたが、STRSPLITの引数として「-」を指定していることにも注意してください。

編集: 私はあなたが提供したスクリプトにもう少し時間を費やしました。スクリプト1と2は実際には機能せず、スクリプト3も次のように機能します(余分なforeachなし):

a = load 'file1' as (str:chararry);
b = load 'file2' as (num:int, ch:chararry);
a1 = foreach a generate flatten(STRSPLIT(str,'_',2));
c = join a1 by (int)($0), b by num;
dump c;

問題の原因については、大げさな推測をして、これが(Pigのドキュメントに記載されているように)pigの実行サイクルの最適化と組み合わされている可能性があると言います。

内部スキーマが空のバッグをフラット化すると、結果のリレーションのスキーマはnullになります。

あなたの場合、STRSPLITの結果のスキーマは実行時まで不明であると思います。

edit2:わかりまし た、これが私の理論の説明です:

これは、スクリプト2の完全な-explain-出力であり、スクリプト3の出力です。ここに面白い部分を貼り付けます。

|---a2: (Name: LOForEach Schema: num#288:int,ch#289:chararray)
|   |   |
|   |   (Name: LOGenerate[false,false] Schema: num#288:int,ch#289:chararray)ColumnPrune:InputUids=[288, 289]ColumnPrune:OutputUids=[288, 289]
|   |   |   |
|   |   |   (Name: Cast Type: int Uid: 288)
|   |   |   |
|   |   |   |---num:(Name: Project Type: int Uid: 288 Input: 0 Column: (*))

上記のセクションはスクリプト2用です。最後の行を参照してください。これは、の出力にflatten(STRSPLIT)タイプの最初の要素があることを前提としてintegerいます(スキーマをそのように提供したため)。しかし実際STRSPLITには、フィールドnullとして扱われる出力スキーマがあります。bytearrayしたがって、の出力flatten(STRSPLIT)は実際には(n:bytearray, c:bytearray)です。a1スキーマを指定したため、pigはフィールドへの(の出力への)Javaキャストを作成しようとしnumます。これnumは、実際にはStringbytearrayとして表されるJavaのように失敗します。このjava-castは失敗するため、pigは上記の行で明示的なキャストを作成しようとさえしません。

スクリプト3の状況を見てみましょう:

|---a2: (Name: LOForEach Schema: num#85:int,ch#87:bytearray)
|   |   |
|   |   (Name: LOGenerate[false,false] Schema: num#85:int,ch#87:bytearray)ColumnPrune:InputUids=[]ColumnPrune:OutputUids=[85, 87]
|   |   |   |
|   |   |   (Name: Cast Type: int Uid: 85)
|   |   |   |
|   |   |   |---(Name: Project Type: bytearray Uid: 85 Input: 0 Column: (*))

最後の行を参照してください。ここでの出力a1は適切に扱われbytearray、ここでは問題ありません。そして最後から2番目の行を見てください。bytearraypigはからへの明示的なキャスト操作を試みます(そして成功します)integer

于 2012-09-03T06:11:32.590 に答える