我是初学者,正在学习 Pig latin。需要从文件中提取记录。已经创建了两个文件 T1 和 T2,一些元组是两个文件共有的,所以需要提取仅存在于 T1 中的元组,并且需要省略 T1 和 T2 之间的公共元组。有人可以帮帮我吗...
谢谢
我是初学者,正在学习 Pig latin。需要从文件中提取记录。已经创建了两个文件 T1 和 T2,一些元组是两个文件共有的,所以需要提取仅存在于 T1 中的元组,并且需要省略 T1 和 T2 之间的公共元组。有人可以帮帮我吗...
谢谢
首先你要看看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 ;
我相信有一种更有效的方法来完成它,特别是如果 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。