文章目录
Apache Parquet
1. Parquet格式概述
Parquet是经常在Hadoop生态系统中被使用到的一种高效的列式存储文件格式。
首先我们通过一个例子来对比一下行式存储格式和列式存储格式在存储形式上的差别。假如我们有一张用户表user,包含user_name、phone和age三个字段:
user_name | phone | age |
---|---|---|
Flink | 15011112222 | 5 |
Spark | 15011113333 | 10 |
Hadooop | 15011110000 | 15 |
行式存储格式在底层系统的存储形式是这样的:
而列式存储格式在底层系统的存储形式是这样的:
从存储形式上,列式存储格式有两个明显的优势:
- 只需查询那些需要查询的列,而不必像行式存储那样无论查询多少列都要返回整行数据,这就可以大大地减少IO操作。
- 相同数据类型的数据放在一起存储可以提高压缩率,减少存储成本。
2. Parquet文件结构
Parquet文件主要由4个部分组成:
- Row Group:Parquet文件在水平方向被切分为多个Row Group
- Column Chunk:每个Row Group都保存所有列的某个范围内的值,而这个范围内某一列的值就对应一个Column Chunk
- Page:一个Column Chunk由多个Page组成,Page是最小的压缩和编码单位。
- Footer:每个Parquet文件的末尾是一个Footer,它保存了文件的元数据信息和统计信息。上图右侧,Footer中的FileMetaData保存着所有列的起始位置,当读取文件时,首先会去读这个FileMetaData来找到要查找的Column Chunk。
Apache ORC
1. ORC格式概述
Apache ORC(全称Optimized Row Columnar)官网阐述了创建此种文件格式的背景:
ORC文件格式是为了大规模加速Apache Hive,并提高向Apache Hadoop存储数据的效率而创建的。其核心就是实现减少存储文件的大小并进行高速的数据处理。
ORC是专门为Hadoop工作负载设计的一种列式文件格式。它针对大规模流式数据读取进行了优化,而且能快速地查找所需的行记录。列式存储格式可以只读取、解压缩和处理当前查询所需的数据。因为ORC文件是类型感知的,所以存储数据的时候,ORC会选择最合适的编码并在写数据时构建内部索引。
2. ORC文件结构
ORC使用特定于类型的readers和writers,这些readers和writers提供了轻量级的压缩技术,如 dictionary encoding、bit packing、delta encoding和run length encoding,这会输出更小的文件。
下图展示了ORC文件的结构:
1. File Tail
由于HDFS不支持在写入文件后更改文件中的数据,ORC将最高级别的索引存储在文件的末尾(如上图所示)。该文件的尾部由3部分组成:文件元数据、文件footer和postscript。
ORC的元数据信息是使用Protocol Buffers来存储的,其提供了添加新字段而不破坏readers的能力。
2. Postscript
Postscript部分提供了文件其余部分的必要信息,包括文件的Footer、元数据的长度、文件的版本和使用的压缩类型(none/zlib/snappy)。Postscript 是不会被压缩的,并且位于整个文件的尾部。
读取ORC文件的过程是向后遍历形式读取的。ORC reader会读取文件的最后16K字节,这样做的目的是为了尽可能一次性把文件Footer和Postscript读出来。文件的最后一个字节包含Postscript的序列化长度,Postscript必须小于256字节。一旦解析了Postscript,就能知道Footer压缩序列化之后的长度,然后就能对其进行解压并解析。
3. Footer
Footer部分包含文件主体的布局、类型schema信息、行数以及关于每个列的统计信息。
ORC文件被分为3部分:
- Header:头部有’ORC’组成,就是为了确定文件的类型是否是ORC。
- Body:主体包含数据行和索引。
- Tail:尾部为文件级别的信息。
4. Stripe
ORC文件的body部分会被划分为stripes。每个stripe都是独立,有自己的数据行、Footer和PostScript。每个stripe都保存着完整的行数据,也就是一行数据不会出现一部分在一个stripe,而另一部分在另一个stripe的情况。
Stripe也分为3个部分:
- 本stripe中行数据对应的索引
- 数据本身
- 一个stripe footer
索引部分和数据是按列存储的,这样就能只读取那些要查询的列。
3. ORC文件索引
ORC在每个文件中提供了三个级别的索引:
- file级别——存储了关于整个文件中每列的值的统计信息
- stripe级别——存储了每个stripe中每列的值的统计信息
- row级别——存储了每个stripe内每10000行的每列值的统计信息
file级别和stripe级别的列统计信息是存储在一个叫footer的文件中的,因此可以很容易地访问到它们,以确定是否需要读取文件的其余部分。row级别索引既包括每个行组的列统计信息,也包括行组的起始位置。
列统计信息中包括列值的count以及是否存在null值,对于大多数基本数据类型会包括min、max,对于数值类型会有sum。在Hive 1.2中,索引中还会包括布隆过滤器(bloom filter),可以对不存在的数据进行高效的过滤。此外,ORC还可以应用zlib或snappy压缩格式来进一步压缩文件,这就可以大大地减少存储成本。但是,ORC不仅仅如此,它还支持投影,只查询列的某些部分就能找到满足条件的数据。
Parquet和ORC的区别
Parquet格式和ORC格式的主要区别:
- ORC存储格式要比Parquet压缩率更好,这意味着ORC格式的文件占用更少的存储空间。
- Parquet格式对嵌套列的支持比较友好,可以只查询某个列中的嵌套子列,而不用查询其他的子列。
- ORC支持ACID事务,而Parquet目前还不支持。