前言
补充上一篇文章Hudi Spark源码学习总结-spark.read.format(“hudi”).load,由于上篇文章篇幅已经比较长了,所以单独写一篇补充一下,没有读过的可以先阅读一下,我们在上篇文章讲到resolveBaseFileOnlyRelation
返回的是HadoopFsRelation
,那么如果返回BaseFileOnlyRelation
呢?
起因
其实除了HadoopFsRelation
、BaseFileOnlyRelation
还有IncrementalRelation
、MergeOnReadSnapshotRelation
、MergeOnReadIncrementalRelation
、HoodieBootstrapRelation
,之所有要单独看一下BaseFileOnlyRelation
,是因为我们从提交历史上可以看出,一开始默认的就是HadoopFsRelation
后来添加了自定义的BaseFileOnlyRelation
,然后现在回退成了HadoopFsRelation
,查看对应PR了解了一下原因
添加BaseFileOnlyRelation
的PR:[HUDI-3338] custom relation instead of HadoopFsRelation,原因是:目前,HadoopFsRelation
将使用实际分区路径的值作为分区字段的值。但是,与普通表不同,Hudi在Parquet文件中保留分区值。在某些情况下,实际分区路径的值和分区字段的值是不同的。因此,这里实现了BaseFileOnlyViewRelation
,通过它,Hudi可以管理自己的关系。
回退为HadoopFsRelation
的PR:[HUDI-3902] Fallback to HadoopFsRelation in cases non-involving Schema Evolution,原因是:Spark的一些优化规则(以及一些其他处理)是基于HadoopFsRelation
的使用,这导致当我们依赖自定义Relation
时,这些优化没有得到应用。我们可以在[HUDI-3338]的PR的下面可以看到,有commiter提出,使用BaseFileOnlyRelation
后查询性能相比于之前的HadoopFsRelation
下降了大约一倍,这是因为Spark仅在少数地方做了查询优化,其中一个地方就是我们在上篇文章中讲到的FileSourceStrategy
,我们看到[HUDI-3902]虽然回退到HadoopFsRelation
,但是貌似并没有处理分区路径值的问题,所以后面又提了一个PR:
PR:[HUDI-3204] Fixing partition-values being derived from partition-path instead of source columns,这个PR添加了自定义FileFormat
:Spark24HoodieParquetFileFormat
,它重写了ParquetFileFormat
的buildReaderWithPartitionValues
方法。其中的关键点是添加了参数shouldAppendPartitionValues
来判断是否将分区路径中的值添加为分区字段的值。
1 | if (shouldAppendPartitionValues) { |