如果hdfs是大数据分布式存储文件系统的标准的话,parquet是大数据文件格式的事实标准。
Apache Parquet 是一个列存储格式,主要用于 Hadoop 生态系统。与数据处理框架、数据模型和编程语言无关。Cloudera的大数据在线分析(OLAP)项目Impala中使用该格式作为列存储。
核心的特点是:
1)列存储格式 可以过滤掉不需要的列,从而大大提高读取的效率。
2)Parquet为Hadoop生态系统中的所有项目提供支持高效率压缩的列式数据表达,而且与数据处理框架、数据模型或编程语言都没有关系。 Parquet支持对某一列数据进行压缩,未来还会实现更多的编码方式。将编码的概念与压缩分开,Parquet的用户可以直接对编码数据进行实施和操作,而不需要经历先解压再压缩的过程。
3)数据查找的时候,支持向量,大大提高查找的速度。
一、spark sql下的parquet意义再思考
1)速度更快:从使用spark sql操作普通文件csv和parquet的速度对比上来看,基本上而言,大多数情况下,使用parquet比使用普通文件提升10倍左右,假如做日志分析等程序;如果用普通文件运行不起来,但是如果用parquet格式,则能跑起来。
2)如果hdfs是大数据分布式存储文件系统的标准的话,parquet是大数据文件格式的事实标准。
3)parquet的压缩算法非常稳定出色,在spark sql 中对压缩计算的处理可能无法正常完成(比如会导致lost task ,lost executor),但是此时如果使用parquet就可以正常的完成。Parquet极大的减少了磁盘io压力,只读取所需要的数据,极大的提高了读取的效率。通常情况下会减少75%的存储空间。这就意味着同样的数据,数据完全不变的情况下,spark计算的输入数据的空间就减少了75%。
4)Spark底层默认文件格式是:parquet,由此也会极大减少spark sql处理数据的时候的数据输入内容,尤其是在spark1.6.x中推出的下推过滤器在一些情况下,可以极大的进一步减少磁盘的io和内存的占用。而且,下推是在框架优化的时候自动处理的。
5)spark1.6.x+parquet极大的提升了数据扫描的吞吐量,这极大的提高了数据查找的速度。
根据老师的测试:spark1.6.x和spark1.5.x相比提升了1倍左右,spark1.6.x+parquet的时候也使得CPU的使用也进行了极大的优化,有效的降低了CPU的使用。
6)采用parquet可以极大的优化spark的调度和执行,我们测试表面spark如果采用parquet可以有效的减少stage的执行消耗,同时可以优化执行路径。
7)正如Twiter,用parquet会降低存储的成本约70%。
二、parquet内幕揭秘
名词解释:
- 1 optional 表示有1个或者0个(只有这俩种情况)
- 2 repeated 表示有0个或者多个(大于等于2个,有大于等于俩种情况)
- 3 required 表示有且只有一个(只有一个这一种情况)
举例说明:
AddressBook中蓝色的部分称为尾节点,实际上parquet把一个树状结构,通过巧妙的编码算法,转换成二维表结构。其转换的Striping/Assembly算法算法大概原理如下:
就数据本身而言,只考虑叶子节点,因为实际的数据只在叶子节点,其他的节点可以理解为数据的元数据。记录数据本身以外的数据。
Column | Max Definition level | Max Repetition level |
Owner (因为owner是Required,所以有1个) | (因为Definition是要在为0个的情况下才记录当前的深度,如果不是0个的情况下,Definition Level是不需要的) 这种情况下即为 0 | (因为要重复,只有repeated类型的field需要Repetition Level ,所以required的Reppetition的大小为0) |
ownerPhoneNumbers (ownerPhoneNumbers是repeated,有0个或者多个) | (ownerPhoneNumbers是repeated,有0个的情况,所以从根节点算起(不包括根节点)的深度为1,也就是只从根节点算起的第几个子节点,也就是为1) | (ownerPhoneNumbers是repeated,有多个的情况,所以从根节点算起(不包括根节点)的深度为1,也就是只从根节点算起的第几个子节点,也就是为1) |
name (因为name是Required,所以有1个) | (name只有一种情况,那就是只有一个的情况,所以不需要repetition level,因为定义是这样定义的,当有0个情况时才有repetition level,所以为0个)但是其父节点contacts有0个的情况并且repetition level为1,所以从根节点算起,最终name的repetition level的大小为1 | (name只有一种情况,那就是只有一个的情况,所以不需要Repetition level,因为定义是这样定义的,当有多个情况时才有Repetition level,所以为0个)但是其父节点contacts有多个的情况并且Repetition level为1,所以从根节点算起,最终name的Repetition level的大小为1 |
phoneNumber (因为phoneNumber是optional,所以有0个或者1个) | 有0个的情况,所以从根节点开始,phoneNumber=1(contacts 的repetion level)+0(phoneNumber repetition level) =2 | 没有多个的情况,所以从根节点开始,phoneNumber=1(contacts 的Repetition level)+1(phoneNumber Repetition level) =2 |
总结:
1、看repetition level是否在父节点repetition level的基础上是否加1,就看是不是repeated类型的。
2、看definition level是否在父节点definition level的基础上是否加1,就看是不是有0个的情况类型的。(optional和repeated)
3、在具体的parquet文件存储的时候有三个核心的组成部分:
A)storage format:parquet定义了具体的数据内部的类型和存储格式;独立的文件格式,不需要依赖其他。
B)object model converters:parquet中负责计算框架中数据对象和parquet文件中具体类型的映射
C)object model,但是parquet在处理自己的object model定义的存储格式,比如Avro具有自己的object model,但是parquet在处理相关的格式的数据的时候使用自己的object model来存储。映射完成后,parquet会进行自己的column encoding,然后存储成为parquet格式的文件。
4、parquet三大组件
1)parquet-format(parquet storage format)
2)parquet-mr(读取,input/output)
3)parquet-compatility(兼容性)
注意:学了本节课,可以出一道面试题:spark底层的文件格式是什么?
答:Parquet
parquet-mr(读取,input/output)深入思考:
对于一个parquet文件而言,数据会被分成row group(里面包含很多的列column),而每个column有三个重要的属性:
1、definition level
2、repetition level
3、data本身,而 column在parquet中是以page的方式存在的,page中有repetition level和repetition level data等内容;
再次强调rowGroup,这个概念很重要。IMF成员必须弄清楚。Row Group 在parquet 是数据读写的缓存单元,所以对Row Group 的设置会(日志分析的话,我们一般建议把Row Group的缓存大小配置成256MB,很多人的配置都是大约1G,如果想最大化运行效率的话,强烈建议和hdfs的block大小一致,并且不需要格式化。)
注:本学习笔记来自DT大数据梦工厂 微信公众号:DT_Spark 每晚8点YY永久直播频道:68917580