我正在编写自定义的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
电话是否有任何问题?
答案 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.
希望有助于指导您的自定义代码的设计。