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

Custom InputFormat.getSplits() never called in 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;

CombineHiveInputFormat 上使用 HiveInputFormat 时,对 getSplits 的调用被正确地委托给了我的 InputFormat,一切正常。但是,我想让其他用户可以轻松使用我的 InputFormat、OutputFormat 等,因此我宁愿不必经历这些。此外,如果可能的话,我希望能够利用组合拆分。

另一种解决方法是创建 StorageHandler。但是,我不想这样做,因为这使得所有 table 都由 StorageHandler 支持非本地(因此所有 reducer 都写入一个文件,不能 LOAD DATA 进入 table,以及其他我想从本地 tables) 保留下来的细节。

最后,我可以让我的 InputFormat 实现 CombineHiveInputFormat.AvoidSplitCombination 绕过大部分 CombineHiveInputFormat,但这只在 Hive 1.0 中可用,我希望我的代码可以与早期版本的 Hive 一起使用(至少回到 0.12).

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

是否有人编写了覆盖 getSplits 的自定义 FileInputFormat 以用于 Hive?让 Hive 将呼叫委托给您必须克服的 getSplits 是否有任何问题?

通常在这种情况下,您不理会拆分,以便您可以获得块的数据局部性,并让您的 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.

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