parquet格式的模式演化

jqjz2hbq  于 2021-06-02  发布在  Hadoop
关注(0)|答案(2)|浏览(385)

目前我们正在生产中使用avro数据格式。在使用avro的几个优点中,我们知道它在模式演化中是好的。
现在我们正在评估Parquet格式,因为它在读取随机列时效率很高。因此,在继续前进之前,我们关注的仍然是模式演化。
有人知道模式进化在Parquet地板中是可能的吗?如果有,怎么可能?如果没有,为什么不可能。
一些资源声称这是可能的,但它只能在末尾添加列。
这是什么意思?

carvr3hs

carvr3hs1#

除上述答案外,另一个选项是

"spark.hadoop.parquet.enable.summary-metadata" to "true"

它的作用:当您编写文件时,它会用模式创建摘要文件。您将看到摘要文件 '_metadata' 以及 '_common_metadata' 保存后的后缀。这个 _common_metadata 是每次读取Parquet文件时都会读取的压缩模式。这使得读取非常快,因为您已经有了模式。spark查找这些模式文件(如果存在)以获取模式。
注意,这使得写入速度非常慢,因为spark必须合并所有文件的模式并创建这些模式文件。
我们有一个类似的情况,Parquet模式发生了变化。我们所做的是将上面的配置设置为 true 在模式更改之后的某个时间,以便生成模式文件,然后将其设置回 false . 我们不得不在慢写上妥协一段时间,但在生成模式文件之后,将其设置为 false 达到了目的。还有一个额外的好处就是读取文件的速度更快。

hs1rzwqc

hs1rzwqc2#

模式演化可能(非常)昂贵。
为了找出模式,您基本上必须读取所有Parquet文件,并在读取期间协调/合并它们的模式,这可能会很昂贵,具体取决于数据集中有多少文件或/或列。
因此,自Spark1.5以来,默认情况下它们关闭了模式合并。你可以随时打开它)。
由于模式合并是一个相对昂贵的操作,而且在大多数情况下不是必需的,因此我们从1.5.0开始默认关闭了它。
如果没有模式演化,您可以从一个Parquet文件中读取模式,并且在读取其余文件时假定它保持不变。
Parquet模式的演化依赖于实现。
例如,Hive有一个旋钮 parquet.column.index.access=false 可以设置为按列名而不是按列索引Map架构。
然后你也可以删除列,而不仅仅是添加。
如上所述,它依赖于实现,例如,impala无法正确读取此类Parquet表(在最近的impala2.6版本中已修复)[参考]。
apachespark从2.0.2版开始,似乎仍然只支持添加列:[reference]
用户可以从一个简单的模式开始,然后根据需要逐渐向模式中添加更多的列。这样,用户可能会得到多个具有不同但相互兼容模式的Parquet文件。现在,parquet数据源能够自动检测这种情况并合并所有这些文件的模式。
ps:我看到一些人为了更灵活地进行模式更改而做的事情是,他们在实际Parquet表的顶部创建一个视图,将两个(或更多)不同但兼容的模式Map到一个公共模式。
假设您添加了一个新字段( registration_date )又掉了一栏( last_login_date )在您的新版本中,则如下所示:

CREATE VIEW datamart.unified_fact_vw
AS
SELECT f1..., NULL as registration_date 
FROM datamart.unified_fact_schema1 f1
UNION ALL
SELECT f2..., NULL as last_login_date
FROM datamart.unified_fact_schema2 f2
;

你有主意了。很好的一点是,它可以在hadoop方言的所有sql中工作(如我上面提到的hive、impala和spark),并且仍然具有parquet表的所有优点(列存储、 predicate 下推等)。
p、 补充一些关于 common_metadata spark可以创建的摘要文件,以使此答案更完整。
看看spark-15719
Parquet地板摘要文件现在不是特别有用,因为

- when schema merging is disabled, we assume 
   schema of all Parquet part-files are identical, 
   thus we can read the footer from any part-files.

- when schema merging is enabled, we need to read footers 
  of all files anyway to do the merge.

On the other hand, writing summary files can be expensive,
because footers of all part-files must be read and merged. 
This is particularly costly when appending a small dataset 
to a large existing Parquet dataset.

所以有些观点是反对的 common_metadata :
当目录由混合了不同模式的Parquet文件组成时,公共元数据允许读者为整个目录找出一个合理的模式,而不必读取每个单独文件的模式。由于hive和impala可以从hive元存储访问所述文件的sql模式,因此它们可以立即开始处理单个文件,并在读取时将每个文件与sql模式匹配,而不是事先探索它们的公共模式。这使得hive和impala不需要公共元数据特性。
即使spark在没有sql模式的情况下处理Parquet文件(除非使用sparksql),因此在理论上可以受益于公共元数据,但是这个特性仍然被认为没有用处,因此在spark-15719中默认被禁用。
即使这个特性对查询有用,在编写过程中仍然是一个负担。元数据需要维护,这不仅速度慢,而且容易出现竞速条件和其他并发问题,缺乏原子性保证,并且容易由于过时或不一致的元数据而导致数据正确性问题。
该功能没有文档记录,似乎被认为是不推荐的(只有“似乎是”,因为它似乎从来没有得到官方的支持,不支持的功能也不能被否决)。
cloudera的一位工程师说:“我不知道读取端的行为是否发生了变化,以避免在 common_metadata 文件存在。但不管怎样,首先编写这个文件是一个巨大的瓶颈,给我们的客户带来了很多问题。我强烈建议他们不要费心去生成那个元数据文件。”
“\u common\u metadata”和“\u metadata”文件是特定于spark的,不是由impala和hive编写的,例如,也许还有其他引擎。
不过,spark中的摘要元数据文件可能仍然有它的用例—当没有并发性和上面描述的其他问题时—例如,一些流式处理用例—我想这就是为什么spark没有完全删除此功能的原因。

相关问题