Apache Parquet设计解读

2022-04-18  本文已影响0人  Caucher

官网地址:https://parquet.apache.org/docs
编码:https://www.waitingforcode.com/apache-parquet/encodings-apache-parquet/read
Nested类型编码参考文章:Dremel: interactive analysis of web-scale datasets
Nested类型编码参考解释:https://github.com/julienledem/redelm/wiki/The-striping-and-assembly-algorithms-from-the-Dremel-paper

1. Overview

Parquet是Hadoop生态里面一个比较流行的列存储格式。它存在的意义就是最大化利用压缩的列存储表示。
当然支持各种压缩和编码模式:

注意,总的来说,Parquet是一个非常底层的文件存储技术,它和任何数据处理技术、软件都是正交的,这些技术也都可以用Parquet来存文件。

Parquet is built from the ground up with complex nested data structures in mind, and uses the [record shredding and assembly algorithm] described in the Dremel paper. We believe this approach is superior to simple flattening of nested name spaces

2. Concepts

总结一下这个概念,一个文件可能逻辑上包含若干行组,每个行组中,每个列构成一个列切片,列切片内由多个页构成,页是最小压缩单元。

编者绘制了下图帮助概念理解。


image.png

在并行化级别方面:

3. File Format

一个文件用Parquet来存,基本格式如下图:

3.1 Configurations

对于Parquet,有两个重要的参数配置:

3.2 Metadata

元数据有三个级别,文件元数据,列(chunk)元数据,页元数据。

3.3 Types

类型支持的原则是尽量少,因为Parquet一般不直接面向用户,这里只关注类型如何在磁盘中存储。更复杂的类型,比如String,可以用BYTE_ARRAY进行支持,再额外加一个注解表名如何解释这个BYTE_ARRAY即可。这样只用实现很少量几种类型的代码,就可以表示多种用户类型。


image.png

3.4 Nested Encoding

这里是说层次化类型的编码。举个例子:
如下图:想json,xml等类型一样,数据文件中的列也可能是嵌套复合类型。这些类型不仅仅是列表,map这么简单,而是组合类型的不断组合,理论上有无限深度的。

image.png

要处理这样类型的列,就需要先展平,编码,用的时候子再解码恢复结构查询。
下面三个小节,分别解决这个过程中的三个问题:

  1. 层次化记录的无损表示;
  2. 列的快速编码;
  3. 高效解码重组。

3.4.1 Repetition and Definition Levels

在一个列式存储文件中,只给定某两个值,我们是没法确定它们是来自一条record还是两条记录的,因为存在重复类型的这个概念(如上图Name列,其实可以理解为列表类型)。为了得以区分,定义了重复级别和定义级别两个概念。

3.4.1.1 repetition levels

3.4.1.2 definition levels

定义级别是给所有null值的一个属性,把位置定义清楚。定义级别d描述的是null是在哪一级别的缺省。

3.4.1.3 encoding

最终的编码是非常紧凑的。每个列由多个block组成,每个block有两种levels,有具体的数值。这些levels也不是全都按序存储,主要是按需存储,bit能省则省,一些隐含关系都被挖掘出来。

3.4.2 Splitting Records into Columns

本节聚焦于如何将原始数据都覆成列格式:


image.png

3.4.3 Record Assembly

通过一个有限自动机把需要的数据组合起来。
【编者:我自己也没看进去这部分内容,有兴趣的朋友可以参考论文和代码再研究下。】


image.png

3.5 Data Pages

数据页中,包含定义级别,重复级别,和编码后的数据值。如果数据全都是Required,并且不嵌套,那就不需要这两个级别的信息,而只有编码后的数据值。

3.5.1 Encoding

3.5.1.1 Plain

支持所有类型,最简单的存储方式。

3.5.1.2 Dictionary Encoding

image.png

3.5.1.3 Run Length Encoding / Bit-Packing Hybrid

3.5.1.4 Bit-packed (Deprecated)

废弃的bit-packed非常简单,就是每个类型固定宽度,然后按顺序存储就可以了。但注意是bit级别的,粒度是很细的。因为它性能一般,完全不如RLE或者和RLE混合,目前只是为了兼容性而存在。
用于:

3.5.1.5 Delta Encoding

支持INT32, INT64,和字节数组类型。

3.5.1.6 Delta-length byte array

专门用于字节数组。

3.5.1.7 Byte Stream Split

用于浮点数。
把每一位单独抽出来,虽然总体大小没有减少,但是利于后续压缩算法压缩。

上一篇下一篇

猜你喜欢

热点阅读