1.介绍

Apache Parquet 是 Hadoop 生态圈中一种新型列式存储格式,它可以兼容 Hadoop 生态圈中大多数计算框架(Mapreduce、Spark 等),被多种查询引擎支持(Hive、Impala、Drill 等),并且它是语言和平台无关的。

2.特点:列式存储

Parquet文件存储格式的特点:列式存储,相对于关系数据库中通常使用的行式存储,在使用列式存储时每一列的所有元素都是顺序存储的
列式存储相对于行式存储的优点:

  1. 查询的时候不需要扫描全部的数据,而只需要读取每次查询涉及的列,这样可以将I/O 消耗降低 N 倍。
  2. 由于每一列的成员都是同构的,可以针对不同的数据类型使用更高效的数据压缩算 法,进一步减小 I/O。
  3. 适配多种计算框架Parquet 是语言无关的,而且不与任何一种数据处理框架绑定在一起,适配多种语言和组件,能够与 Parquet 配合的组件有:
  • 查询引擎: Hive, Impala, Pig, Presto, Drill, IBM Big SQL
  • 计算框架: MapReduce, Spark, Cascading, Kite

parquet如何加载到hive库上_spark

3.文件格式

Parquet 文件是以二进制方式存储的,是不可以直接读取和修改的,Parquet 文件是自解析的,文件中包括该文件的数据和元数据。
Parquet 文件中存在如下几个概念:

  1. 行组(Row Group):按照行将数据物理上划分为多个单元,每一个行组包含一定的行数,在一个 HDFS 文件中至少存储一个行组,Parquet 读写的时候会将整个行组缓存在内存中,所以每一个行组的大小是由内存大的小决定的。
  2. 列块(Column Chunk):在一个行组中每一列保存在一个列块中,行组中的所有列连续的存储在这个行组文件中。不同的列块可能使用不同的算法进行压缩。
  3. 页(Page):每一个列块划分为多个页,一个页是最小的编码的单位,在同一个列块 的不同页可能使用不同的编码方式。

例:下图展示了一个 Parquet 文件的内容,一个文件中可以存储多个行组,文件的首位都是该文件的 Magic Code,用于校验它是否是一个 Parquet 文件,Footer length 了文件元数据的大小,通过该值和文件长度可以计算出元数据的偏移量,文件的元数据中包括每一个行组的元数据信息和该文件存储数据的 Schema 信息。

parquet如何加载到hive库上_parquet如何加载到hive库上_02

4.常见的四种压缩格式

parquet如何加载到hive库上_hadoop_03

Spark默认使用snappy压缩格式,需要改变可以在SparkConf/Session程序入门中设置:

parquet如何加载到hive库上_列式存储_04

5.Spark读写Parquet文件

val peopleDF = spark.read.json("examples/src/main/resources/people.json")
// DataFrames can be saved as Parquet files, maintaining the schema information
peopleDF.write.parquet("people.parquet")
val parquetFileDF = spark.read.parquet("people.parquet")

关于分区:

By passing path/to/table to either SparkSession.read.parquet or SparkSession.read.load, Spark SQL will automatically extract the partitioning information from the paths.
Notice that the data types of the partitioning columns are automatically inferred. Currently,numeric data types, date, timestamp and string type are supported. Sometimes users may not want to automatically infer the data types of the partitioning columns. For these use cases, the automatic type inference can be configured by spark.sql.sources.partitionColumnTypeInference.enabled, which is default to true. When type inference is disabled, string type will be used for the partitioning columns.
Starting from Spark 1.6.0, partition discovery only finds partitions under the given paths by default. For the above example, if users pass path/to/table/gender=male to either SparkSession.read.parquet or SparkSession.read.load, gender will not be considered as a
partitioning column. If users need to specify the base path that partition discovery should start with, they can set basePath in the data source options. For example, when path/to/table/gender=male is the path of the data and users set basePath to path/to/table/, gender will be a partitioning column.