如何使用Apache Pig在两个包中找到常见项的子集?

时间:2016-01-03 15:36:17

标签: apache-pig

我想使用Apache Pig在两个列表中找到公共项的子集(= intersect)。

在SQL中,可接受的方式是使用内连接,例如:

C = SELECT * FROM A INNER JOIN B ON A.name=B.name;

但是,使用Pig中的所有高级选项(如DIFF,DataFu和SetIntersect),我不确定它是最好的方式(在性能,MapReduce范例等方面)。

因此,以下两个选项可行 - 但最佳做法是什么?

选项A:

grouped = COGROUP A BY name, B by name;
common = FOREACH grouped {
A1 = ORDER A BY name
B1 = ORDER B BY name
GENERATE SetIntersect(A1,B1);};

选项B:

grouped = COGROUP A BY name, B by name;
common = FOREACH grouped {
GENERATE SetIntersect(A.name,B.name);};

非常感谢任何帮助。

1 个答案:

答案 0 :(得分:0)

如果您的关系具有相同的模式,或者您只对一个字段(例如Name)感兴趣,我可以建议一种方法,对于非常大的文件,它将比SQL风格的JOIN快得多

a = LOAD 'Afile.txt' using PigStorage() as (name:chararray);
b = LOAD 'Bfile.txt' using PigStorage() as (name:chararray);
a_counters = foreach a generate *, 1 as from_a, 0 as from_b;
b_counters = foreach b generate *, 0 as from_a, 1 as from_b;
united = union a_counters, b_counters;
res = foreach (group united by name) generate group, SUM(united.from_a) as from_a, SUM(united.from_b) as from_b;
res = filter res by from_a >=1 and from_b>=1;

res现在只包含两个文件中的名称。这会生成一个MR作业。对于我的巨大文件(数十亿行,数十个字段),与使用JOIN的小时数相比,这种方法在几分钟内完成。

此方法将为每条记录创建一个指示符,表示它来自哪个文件。然后你'连接'这两个文件,并按名称汇总指标。仅存在于文件A中的名称将具有from_a> = 1和from_b == 0.仅存在于文件B中的名称将具有from_b> = 1和from_a == 0.两个文件中存在的名称将具有from_a > = 1且from_b> = 1。