如何在apache pig输出文件中均匀分布数据?

时间:2015-01-22 19:05:08

标签: apache-pig

我有一个带有一些xml的pig-latin脚本,使用XPath UDF提取一些字段,然后存储结果字段:

REGISTER udf-lib-1.0-SNAPSHOT.jar;
DEFINE XPath com.blah.udfs.XPath();

docs = LOAD '$input' USING com.blah.storage.XMLLoader('root') as (content:chararray);

results = FOREACH docs GENERATE XPath(content, 'root/id'), XPath(content, 'root/otherField'), content;

store results into '$output';

请注意,我们在群集中使用了pig-0.12.0,所以我从pig-0.14.0中删除了XPath / XMLLoader类并将它们放在我自己的jar中,以便我可以在0.12中使用它们

以上脚本运行正常并生成我正在寻找的数据。但是,它会生成超过1,900个partfiles,每个文件只有几个mbs。我了解了default_parallel选项,因此我将其设置为128以尝试获得128个partfiles。我最终不得不添加一块来强制减少阶段来实现这一目标。我的脚本现在看起来像:

set default_parallel 128;
REGISTER udf-lib-1.0-SNAPSHOT.jar;
DEFINE XPath com.blah.udfs.XPath();

docs = LOAD '$input' USING com.blah.storage.XMLLoader('root') as (content:chararray);

results = FOREACH docs GENERATE XPath(content, 'root/id'), XPath(content, 'root/otherField'), content;

forced_reduce = FOREACH (GROUP results BY RANDOM()) GENERATE FLATTEN(results);
store forced_reduce into '$output';

同样,这会产生预期的数据。此外,我现在得到128个部分文件。我现在的问题是数据不是均匀分布在部分文件中。有些人有8场演出,有些有100 mb。当我们用RANDOM()对它们进行分组时,我应该预料到这一点。)。

我的问题是什么是限制零件文件数量的首选方法,但它们仍然具有均匀大小?我是猪/猪拉丁语的新手,并假设我以完全错误的方式解决这个问题。

P.S。我关心零件文件数量的原因是因为我想用spark来处理输出,而且我们的spark集合似乎用较少的文件做得更好。

2 个答案:

答案 0 :(得分:0)

我仍在寻找一种直接从pig脚本执行此操作的方法,但是现在我的“解决方案”是在spark脚本的输出中对spark数据进行重新分区。我使用RDD.coalesce函数来重新平衡数据。

答案 1 :(得分:0)

从第一个代码片段开始,我假设它是map only job,因为你没有使用任何聚合。

不使用reducer,而是设置属性pig.maxCombinedSplitSize

    REGISTER udf-lib-1.0-SNAPSHOT.jar;
    DEFINE XPath com.blah.udfs.XPath();

    docs = LOAD '$input' USING com.blah.storage.XMLLoader('root') as (content:chararray);

    results = FOREACH docs GENERATE XPath(content, 'root/id'), XPath(content, 'root/otherField'), content;

    store results into '$output';        
exec;
        set pig.maxCombinedSplitSize 1000000000; -- 1 GB(given size in bytes)
        x = load '$output' using PigStorage();
        store x into '$output2' using PigStorage();

pig.maxCombinedSplitSize - 设置此属性将确保每个映射器读取大约1 GB的数据,并且上面的代码用作身份映射器作业,这有助于您以1GB的部分文件块写入数据。