4

我是初学者,正在学习 Pig latin。需要从文件中提取记录。已经创建了两个文件 T1 和 T2,一些元组是两个文件共有的,所以需要提取仅存在于 T1 中的元组,并且需要省略 T1 和 T2 之间的公共元组。有人可以帮帮我吗...

谢谢

4

2 回答 2

7

首先你要看看this Venn Diagram. 你想要的是除了中间部分之外的一切。所以首先你需要对full outer JOIN数据做一个。然后,由于nulls在键不常见时在外部 JOIN 中创建,因此您将希望过滤 JOIN 的结果以仅包含具有一个空值的行(维恩图的非相交部分)。

这是它在猪脚本中的外观:

-- 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,因为它们具有相同的名称。

现在,C过滤器B只保留带有空值的行。导致:

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

这是你想要的输出,但使用起来有点乱。 D使用bincond(?:) 删除空值。所以最终的输出将是:

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是不必要的。如果您查看 this 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;

这将返回第 1 天没有出现的具有 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(尤其是在映射器周围),但仅使用 50% 的 CPU。

于 2015-12-19T14:46:35.173 回答