Pig 无法读取自己的中间数据

Posted

技术标签:

【中文标题】Pig 无法读取自己的中间数据【英文标题】:Pig cannot read its own intermediate data 【发布时间】:2014-05-14 11:44:08 【问题描述】:

首先,我正在根据集群运行 Apache Pig 版本 0.11.0-cdh4.3.0(重新导出)。但是,我的构建使用 0.11.0-cdh4.5.0,我知道这不是一个明智的决定,但我认为这与我在这里遇到的问题无关,因为它都是 Pig v0.11.0

我有一个结构看起来像这样的脚本(两个自定义 udf 都返回 DataByteArray 类型,这是一个有效的 Pig 类型 afaik):

LOAD USING parquet.pig.ParquetLoader();

FOREACH GENERATE some of the fields

GROUP BY (a,b,c)

FOREACH GENERATE FLATTEN(group) AS (a,b,c), CustomUDF1(some_value) AS d

FOREACH GENERATE FLATTEN(CubeDimensions(a,b,c)) AS (a,b,c) , d

GROUP BY (a,b,c)

FOREACH GENERATE FLATTEN(group) AS (a,b,c), SUM(some_value), CustomUDF2(some_value)

STORE USING parquet.pig.ParquetStorer();

Pig 将其拆分为两个 mapreduce 作业。我不确定 CubeDimensions 是发生在第一个还是第二个,但我怀疑它发生在第一个作业的 reduce 阶段。

所以第二个作业的映射阶段只是读取中间数据,这就是发生这种情况的地方:

“在流中发现意外的数据类型 49。” @org.apache.pig.data.BinInterSedes:422

我看到数字是 48 和 49,并且在 BinInterSedes 类中都不存在:

http://grepcode.com/file/repository.cloudera.com/content/repositories/releases/org.apache.pig/pig/0.11.0-cdh4.3.0/org/apache/pig/data/BinInterSedes.java?av=f

但由于这是 pig 自己的中间输出,我不太明白它可能出错的地方。我的自定义 UDF 都返回一个有效类型,我希望 Pig 肯定只使用它知道的类型进行存储。

任何帮助将不胜感激。

【问题讨论】:

您是否尝试在CustomUDF1 行之后存储您的数据? 我考虑过这一点,但我认为 Pigs BinStorage 对于中间日期会比我们使用的 ParquetStorage 更有效。我会试一试,然后在这里报告。 数据集非常大,所以这可能需要一段时间。如果 DataByteArray 包含指示新记录开始的字节序列(我收集的 0x01 0x02 0x03),这会导致文件损坏吗? 这是个好主意。我不熟悉 Parquet 或 Hadoop 的序列文件,所以我不会有太多帮助。但希望如果您可以检查中间数据,您会发现问题所在。 【参考方案1】:

巧合的是,在 Pig 的中间存储中用于行拆分的序列也出现在自定义 UDF 返回的字节数组之一中。这会导致 pig 在中间某处断开线,并开始寻找数据类型指示。由于它只是在行的中间,因此没有有效的数据类型指示,因此出现错误。

我还不完全确定我将如何解决这个问题。 @WinnieNicklaus 已经提供了一个很好的解决方案,将脚本分成两部分并存储在两者之间。另一种选择是让 UDF 返回一个 Base64 编码的字节数组。这样就不会与 PIG 中间存储发生冲突,因为它使用 CTRL-A、CTRL-B、CTRL-C、TUPLE-INDICATOR,它们都不是字母数字字符。

【讨论】:

以上是关于Pig 无法读取自己的中间数据的主要内容,如果未能解决你的问题,请参考以下文章

无法配置 Pig 将中间文件存储为 LZO 格式

Pig 读取数据作为 databytearray

无法通过在 Azure HDInsight 中运行的 piggybank.jar 使用 PIG 读取 Avro 文件

Pig 无法处理大文件

通过 Pig 转储中间 MR 作业数据

如何在 Pig 中读取 csv 文件中的下一行