1、parquet文件简介
Apache Parquet是Apache Hadoop生态系统的一种免费的开源面向列的数据存储格式。 它类似于Hadoop中可用的其他列存储文件格式,如RCFile格式和ORC格式。
Apache Parquet 是由 Twitter 和 Cloudera 最先发起并合作开发的列存项目,也是 2010 年 Google 发表的 Dremel 论文中描述的内部列存格式的开源实现。和一些传统的列式存储(C-Store、MonetDB 等)系统相比,Dremel/Parquet 最大的贡献是支持嵌套格式数据(Nested Data)的列式存储。嵌套格式可以很自然的描述互联网和科学计算等领域的数据,Dremel/Parquet “原生”的支持嵌套格式数据减少了规则化、重新组合这些大规模数据的代价。
Parquet 的设计与计算框架、数据模型以及编程语言无关,可以与任意项目集成,因此应用广泛。目前已经是 Hadoop 大数据生态圈列式存储的事实标准。
行存和列存的区别
下图是拥有 A/B/C 3 个字段的简单示意表:
在面向行的存储中,例如csv文件,每列的数据依次排成一行,行的存储方式如下所示:
而在面向列的存储中,相同列的数据存储在一起,列的存储如下所示,
从上图,显而易见,行存适用于数据整行读取场景,而列存更适用于读取部分列数据(统计分析等)的场景。
parquet文件的优势
有这样一句话流传:如果说 HDFS 是大数据时代文件系统的事实标准,Parquet 就是大数据时代存储格式的事实标准。Parquet 这种列存的使用场景如下:
- Parquet 是一种支持嵌套结构的列式存储格式
- 非常适用于 OLAP 场景,按列存储和按列扫描
Parquet 这种列存的特点或优势主要体现在两方面
- 更高的压缩比
列存使得更容易对每个列使用高效的压缩和编码,降低磁盘空间。(网上的case是不压缩、gzip、snappy分别能达到11/27/19的压缩比) - 更小的IO操作
使用映射下推和谓词下推,只读取需要的列,跳过不满足条件的列,能够减少不必要的数据扫描,带来性能的提升并在表字段比较多的时候更加明显。
关于映射下推与谓词下推: 映射下推,这是列式存储最突出的优势,是指在获取数据时只需要扫描需要的列,不用全部扫描。
谓词下推,是指通过将一些过滤条件尽可能的在最底层执行以减少结果集。谓词就是指这些过滤条件,即返回bool:true和false的表达式,比如SQL中的大于小于等于、Like、Is Null等。
2、parquet文件结构
从内容和元数据的角度来看,Parquet文件主要包含两部分内容:
- data
- metadata
data是文件中的数据,metadata是文件的元数据信息。数据data首先写入文件,元数据metadata最后写入文件。
图一
图二
从图一和图二所示,一个Parquet有可以分为以下的3个部分:
- Header文件头信息
- Data Block数据信息
- Footer尾部信息
一个Parquet一般主要包含一个header,一个Data以及一个footer。其中一个Data包含多个Row Group。
Header
header中包含了一个4-byte的magic number(PAR1),这个magic number代表当前该文件是是Parquet格式。
Data Block
Data Block是文件存放具体内容的位置,其中就涉及了Parquet文件的结构,是非常重要的部分。针对文件的存储结构展开说明,
关于parquet文件结构的术语如下:
- Block (hdfs Block): 表示hdfs中的块,描述该文件格式的含义不变。该文件格式被设计成在hdfs上很好地工作。
- File: hdfs文件,必须包含文件的元数据。它不需要实际包含数据。
- 行组(Row Group): 数据的逻辑水平分区。行组没有保证的物理结构。行组由数据集中每一列的列块组成。一个行组中包含的具体行数是不确定的
- 列块(Colunm Chunk): 特定列的数据块。它们位于特定的行组中,并保证在文件中是连续的。
- 页(Pages): 列块被划分为页。从概念上讲,页面是一个不可分割的单元,压缩和编码都是针对Page进行的。列块中可以有多个分页类型。
官网文件结构图如下所示,其中一个File包含多个Row groups行组,一个行组中包含多个列块,一个列块对应一列数据,并且一个列块中有多个数据页Page,数据页Page才是文件存放的基本单位,数据页可以进行数据压缩和编码。下图的左边和右边合起来是一个完整的文件,左边在上面,右边在下面。
如上图所示,Parquet 的存储模型主要由 **行组(Row Group)、列块(Column Chuck)、页(Page)**组成。Block和File与Parquet文件结构关系不大。
1、行组,Row Group:一个完整的Parquet文件在水平方向上将被划分为一个或者多个行组,默认一个行组的大小与 HDFS Block 块大小对齐,主要是为了保证Parquet一个行组会被一个Mapper 处理。一个行组中有多少行,是不确定的,和行组以及列块的大小有关系。
2、列块,Column Chunk:行组中的每一列都是一个列块,行组中有n列,就会有n个列块,不过这个n个列块的名字可能一样的,一个列块具有相同的数据类型。
3、页,Page:Parquet 是页存储方式,每一个列块包含一个或者多个页,一个页是最小的编码单位,同一列块的不同页可以使用不同的编码方式。压缩和编码都是针对Page进行的。
也可以用以下的方式显示文件的机构:
4-byte magic number "PAR1"<RowGroup-1 Column 1 Chunk 1-1 + Column Metadata><RowGroup-1 Column 2 Chunk 1-2 + Column Metadata><RowGroup-1 Column N Chunk 1-3 + Column Metadata><RowGroup-2 Column 1 Chunk 2-1 + Column Metadata><RowGroup-2 Column 2 Chunk 2-2 + Column Metadata><RowGroup-2 Column N Chunk 2-3 + Column Metadata><RowGroup-M Column 1 Chunk M-1 + Column Metadata><RowGroup-M Column 2 Chunk M-2 + Column Metadata><RowGroup-M Column N Chunk M-3 + Column Metadata>File Metadata4-byte length in bytes of file metadata4-byte magic number "PAR1"
整个文件有 N 个列,整个文件被划分成M 个行组,每个行组都有N个列,行组中的每个列只有一个Chunk,一个行组就有N个Chunk。文件的元数据信息存储在数据之后,包含了所有列块元数据信息的起始位置。读取的时候首先从文件末尾读取文件元数据信息,再从元数据总其中找到某一个需要的 Column Chunk 信息,并依次读取。
Parquet文件中的数据被划分为多个Row Group。这些Row Group由一个或多个column chunks组成,column chunks对应于数据集中的一列。每个column chunks的数据以page的形式写入。每个pages只包含特定列的值,因此pages是非常好的压缩候选对象,因为它们包含类似的值。
FOOTER
文件的所有元数据信息保存在footer中。footer中的元数据包括version、schema、任何额外的键-值对,以及列元数据。列元数据包括类型、路径、编码、值的数量、压缩大小等。Footer中除了文件元数据之外,它还有一个4字节字段长度的footer length,以及一个4字节的魔术字(PAR1)。
3、parquet文件的元数据(metadata)内容
4、schema的讲解和使用
来源地址:https://blog.csdn.net/weixin_42704604/article/details/128080926