自定义InputFormat.getSplits()从未在Hive中调用

时间:2015-03-18 21:43:17

标签: java apache hadoop mapreduce hive

我正在编写自定义的InputFormat(特别是org.apache.hadoop.mapred.FileInputFormat的子类),OutputFormat和SerDe,用于通过Apache Hive读取的二进制文件。 并非二进制文件中的所有记录都具有相同的大小

我发现Hive的默认InputFormat,CombineHiveInputFormat,没有将getSplits委托给我的自定义InputFormat实现,这会导致所有输入文件在常规的128MB边界上被拆分。这个问题是这个分裂可能在记录的中间,所以所有分裂但第一个分裂很可能看起来有损坏的数据。

我已经找到了一些解决方法,但我对其中任何一个都不满意。

一种解决方法是:

set hive.input.format=org.apache.hadoop.hive.ql.io.HiveInputFormat;

使用HiveInputFormat而不是CombineHiveInputFormat时,对getSplits的调用会被正确委托给我的InputFormat并且一切正常。但是,我想让其他用户可以轻松使用我的InputFormat,OutputFormat等,所以我宁愿不必经历这一点。另外,如果可能的话,我希望能够利用组合拆分。

另一种解决方法是创建StorageHandler。但是,我不喜欢这样做,因为这会使得StorageHandler支持的所有表都是非本机的(所以所有reducers都写到一个文件,不能LOAD DATA进入表,以及其他语言我&# 39; d喜欢保留原生表格。

最后,我可以让我的InputFormat工具CombineHiveInputFormat.AvoidSplitCombination绕过大部分的CombineHiveInputFormat,但这仅适用于Hive 1.0,我希望我的代码能够与早期版本的Hive一起使用(至少回到0.12)。

我在这里的Hive bug跟踪器中提交了一张票,以防这种行为是无意的:https://issues.apache.org/jira/browse/HIVE-9771

是否有人编写了一个自定义FileInputFormat来覆盖getSplits以便与Hive一起使用?将Hive委托给您必须克服的getSplits电话是否有任何问题?

1 个答案:

答案 0 :(得分:1)

通常在这种情况下,您可以单独保留拆分,以便获取块的数据位置,并让RecordReader了解如何从块中的第一条记录开始读取(拆分)并阅读进入下一个区块,最终记录不会在分割的确切结束时结束。这需要一些远程读取,但这是正常的,通常很少。

TextInputFormat / LineRecordReader执行此操作 - 它使用换行符来分隔记录,因此记录自然可以跨越两个块。它将遍历分割中的第一个记录,而不是从第一个字符开始,在最后一个记录中,如果需要读取完整数据,它将读入下一个块。

Where LineRecordReader starts the split by seeking past the current partial record.

Where LineRecordReader ends the split by reading past the end of the current block.

希望有助于指导您的自定义代码的设计。