parquet 简介

参考文章:parquet 简介

Parquet原理

【2019-05-29】Parquet

简介

Apache Parquet是一种能够有效存储嵌套数据的列式存储格式。

面向分析型业务的列式存储格式

由 Twitter 和 Cloudera 合作开发,2015 年 5 月从 Apache 的孵化器里毕业成为 Apache *项目。

Parquet源码 : https://github.com/apache/parquet-mr

Parquet的设计目标:

  • 适配通用性
  • 存储空间优化
  • 计算时间优化

Parquet的原子类型:

parquet 简介

Parquet的逻辑类型:

parquet 简介

 Parquet文件的内部结构:

parquet 简介

Parquet文件由一个文件头(header),一个或多个紧随其后的文件块(block),以及一个用于结尾的文件尾(footer)构成。文件头仅包含
Parquet文件的每个文件块负责存储一个行组,行组由列块组成,且一个列块负责存储一列数据。每个列块中的的数据以页为单位。

列式存储

概念:传统的思维中是按照一条记录一条记录的组织存储,列式存储是竖过来,按照一列一列的方式组织存储。

每次查询数据只针对其中的少数几个字段,这时候列式存储是极佳的选择。

列式存储要解决的问题:

  • 把IO只给查询需要用到的数据
    • 只加载需要被计算的列
  • 空间节省
    • 列式的压缩效果更好
    • 可以针对数据类型进行编码
  • 开启矢量化的执行引擎(不再1条1条的处理数据,而是一次处理1024条数据)

列式存储和行式存储相比的优势:

  1. 可以跳过不符合条件的数据,只读取需要的数据,降低 IO 数据量。
  2. 压缩编码可以降低磁盘存储空间。由于同一列的数据类型是一样的,可以使用更高效的压缩编码(例如 Run Length Encoding 和 Delta Encoding)进一步节约存储空间。
  3. 只读取需要的列,支持向量运算,能够获取更好的扫描性能。

 当时 Twitter 的日增数据量达到压缩之后的 100TB+,存储在 HDFS 上,工程师会使用多种计算框架(例如 MapReduce, Hive, Pig 等)对这些数据做分析和挖掘;

日志结构是复杂的嵌套数据类型,例如一个典型的日志的 schema 有 87 列,嵌套了 7 层。所以需要设计一种列式存储格式,既能支持关系型数据(简单数据类型),又能支持复杂的嵌套类型的数据,同时能够适配多种数据处理框架。

关系型数据的列式存储,可以将每一列的值直接排列下来,不用引入其他的概念,也不会丢失数据。

适配通用性

Parquet只是一种存储格式,它与上层平台、语言无关,不需要与任何一种数据处理框架绑定,目前已经适配的组件包括:

  • 查询引擎:Hive\Impala\Pig\Presto\Drill\Tajo\HAWQ\IBM Big SQL
  • 计算引擎:MapReduce\Spark\Cascading\Crunch\Scalding\Kite
  • 数据模型:Avro\Thrift\Protocol Buffers

Parquet的数据模型

每条记录中的字段可以包含三种类型:required, repeated, optional。最终由所有叶子节点来代表整个schema。

  • 元组的Schema可以转换成树状结构,根节点可以理解为repeated类型
  • 所有叶子结点都是基本类型
  • 没有Map、Array这样的复杂数据结构,但是可以通过repeated和group组合来实现这样的需求

Parquet文件格式

Parquet文件是二进制方式存储的,文件中包含数据和元数据,可以直接进行解析

先了解一下关于Parquet文件的几个基本概念:

  • 行组(Row Group):每一个行组包含一定的行数,一般对应一个HDFS文件块,Parquet读写的时候会将整个行组缓存在内存中。
  • 列块(Column Chunk):在一个行组中每一列保存在一个列块中,一个列块中的值都是相同类型的,不同的列块可能使用不同的算法进行压缩。
  • 页(Page):每一个列块划分为多个页,一个页是最小的编码的单位,在同一个列块的不同页可能使用不同的编码方式。

 

Parquet文件组成:

  • 文件开始和结束的4个字节都是Magic Code,用于校验它是否是一个Parquet文件
  • 结束MagicCode前的Footer length是文件元数据的大小,通过该值和文件长度可以计算出元数据Footer的偏移量
  • 再往前推是Footer文件的元数据,里面包含:

    • 文件级别的信息:版本,Schema,Extra key/value对等
    • 每个行组的元信息,每个行组是由多个列块组成的:
      • 每个列块的元信息:类型,路径,编码方式,第1个数据页的位置,第1个索引页的位置,压缩的、未压缩的尺寸,额外的KV
  • 文件中大部分内容是各个行组信息:

    • 一个行组由多个列块组成
      • 一个列块由多个页组成,在Parquet中有三种页:
        • 数据页
          • 一个页由页头、repetition levels\definition levles\valus组成
        • 字典页
          • 存储该列值的编码字典,每一个列块中最多包含一个字典页
        • 索引页
          • 用来存储当前行组下该列的索引,目前Parquet中还不支持索引页,但是在后面的版本中增加

Parquet 适配多种计算框架

Parquet 是语言无关的,

而且不与任何一种数据处理框架绑定在一起,

适配多种语言和组件,能够与 Parquet 配合的组件有:

  • 查询引擎: Hive, Impala, Pig, Presto, Drill, Tajo, HAWQ, IBM Big SQL
  • 计算框架: MapReduce, Spark, Cascading, Crunch, Scalding, Kite
  • 数据模型: Avro, Thrift, Protocol Buffers, POJOs