4

私は初心者で、豚のラテン語を学んでいます。ファイルからレコードを抽出する必要があります。T1 と T2 の 2 つのファイルを作成しました. 一部のタプルは両方のファイルに共通です. したがって、T1 にのみ存在するタプルを抽出し、T1 と T2 の間の共通のタプルを省略する必要があります. 誰か助けてくれませんか...

ありがとう

4

2 に答える 2

7

まず、 をご覧くださいthis Venn Diagram。あなたが望むのは、中間ビット以外のすべてです。したがって、最初にデータに対して a を実行する必要がありfull outer JOINます。次に、nullsキーが共通でない場合に外部 JOIN で作成されるため、JOIN の結果をフィルタリングして、1 つの null (ベン図の交差しない部分) を持つ行のみを含める必要があります。

これは、豚のスクリプトでどのように見えるかです:

-- T1 and T2 are the two sets of tuples you are using, their schemas are:
-- T1: {t: (num1: int, num2: int)}
-- T2: {t: (num1: int, num2: int)}
-- Yours will be different, but the principle is the same

B = JOIN T1 BY t FULL, T2 BY t ;
C = FILTER B BY T1::t is null OR T2::t is null ;
D = FOREACH C GENERATE (T1::t is not null? T1::t : A2::t) ;

このサンプル入力を使用して手順を説明します。

T1:      T2:
(1,2)    (4,5)
(3,4)    (1,2)

B完全な外部 JOIN を実行すると、次のようになります。

B: {T1::t: (num1: int,num2: int),T2::t: (num1: int,num2: int)}
((1,2),(1,2))
(,(4,5))
((3.4),)

T1は左タプル、T2は右タプルです。それらは同じ名前を持っている::ため、どの を識別するために使用する必要があります。t

ここで、null を含む行のみが保持されるようにCフィルター処理します。Bその結果:

C: {T1::t: (num1: int,num2: int),T2::t: (num1: int,num2: int)}
(,(4,5))
((3.4),)

これは必要な出力ですが、使用するのは少し面倒です。 D(?:) を使用しbincondて null を削除します。したがって、最終的な出力は次のようになります。

D: {T1::t: (num1: int,num2: int)}
((4,5))
((3.4))

更新:
結合の左側 (T1) (または、入れ替える場合は右側 (T2)) のみを保持する場合。あなたはこれを行うことができます:

-- B is the same

-- We only want to keep tuples where the T2 tuple is null
C = FILTER B BY T2::t is null ;
-- Generate T1::t to get rid of the null T2::t
D = FOREACH C GENERATE T1::t ;

ただし、元のベン図を振り返ってみると、フルを使用するJOIN必要はありません。これを見るとdifferent Venn Diagram、余分な操作なしで必要なセットがカバーされていることがわかります。したがって、次のように変更Bする必要があります。

B = JOIN T1 BY t LEFT, T2 BY t ;
于 2013-07-31T20:02:11.450 に答える
1

特に T1 と T2 が非常に大きい場合は、より効率的な方法があると思います。ファイルごとに数十億行のデータセットに取り組んでおり、T1 には存在しない T2 の行にのみ関心があります。両方のファイルのスキーマは同じで、サイズも同様です。

T1 = load '/path/to/file1' using PigStorage() as (
  f1,
  f2,
  f3);

T1 = foreach T1 generate
  $0.., --all fields
  1 as day1,
  0 as day2);

T2 = load '/path/to/file2' using PigStorage() as (
  f1,
  f2,
  f3);

T2 = foreach T2 generate
  $0.., --all fields
  0 as day1,
  1 as day2);

T3 = union T1, T2;
-- assuming f1 is your join field
T3grouped = foreach (group T3 by f1) generate 
   flatten(T3),
   sum(T3.day1) as day1,
   sum(T3.day2) as day2;

T3result = filter T3grouped by day1==0;

これにより、day1 には表示されなかった f1 を持つ行が返されます。と同等です

T3 = T2 by f1 LEFT OUTER, T1 by f1;
T3result = filter T3 by T1::f1 is null

しかし、はるかに高速です。UNION バージョンは約 10 分で実行され、JOIN バージョンは 2 時間以上実行されています (まだ完了していません)。カウンターを見ると、UNION バージョンはより多くの I/O を生成しますが (特にマッパーの周りで)、CPU を 50% しか使用していません。

于 2015-12-19T14:46:35.173 に答える