大数据存储格式parquet是怎样的
这篇文章将为大家详细讲解有关大数据存储格式parquet是怎样的,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。
成都创新互联公司长期为近千家客户提供的网站建设服务,团队从业经验10年,关注不同地域、不同群体,并针对不同对象提供差异化的产品和服务;打造开放共赢平台,与合作伙伴共同营造健康的互联网生态环境。为兰西企业提供专业的网站建设、成都做网站,兰西网站改版等技术服务。拥有十年丰富建站经验和众多成功案例,为您定制开发。
大数据存储格式-parquet
为什么需要列式存储
首先我们从关系数据库入手,来看关系数据库的一些常见查询。对于关系数据库而言,我们常见的查询一般有详情查询或者统计分组,但是如果是大数据量的情况下,关系数据库是不能很好的支持统计类的查询,所以一般关系数据库多有于对OLTP业务,那么常见的大数据的查询有个特点,由于数据量很大,获取具体的详情数据意义不大,所以基本都是统计类的查询,如:select count(1) cnt,ip from access_log group by ip,查询每个ip的访问次数。当然也可能有查询详细做深度的数据分析。
对于查询速度当然是越快越好,我们可以从以下几个方面来提高这个系统的查询速度(当然缓存不在考虑的范畴内),1.查询系统框架的优化,这里可能包含了(执行计划啊,分布式计算等等等),2.底层文件存储格式的优化,尽量减少IO.3.当然还有索引技术.
针对上面的sql:select count(1) cnt,ip from access_log group by ip
我们假设access_log的格式如下: access_log{ string ip; string access_time; ............(其他N个属性)
}
如果是行存储:
我们需要读取一行的所有数据,然后获取其中的ip字段,在做分组统计。增加的磁盘的IO,同时也增加了计算压力.
如果是列存储会如何:
对于上面的统计,我们只需要读取IP就可以,读取不需要的列信息,这就是列存储对于大数据的统计类查询的优点所在,当然除此之外大数据本身的稀疏性,采用列式可能更好的去优化存储结构,减少存储空间.
parquet介绍
parquet是twitter在2013年开源的数据结构,google的Dremel: [Interactive Analysis of Web-Scale Datasets http://research.google.com/pubs/pub36632.html](Interactive Analysis of Web-Scale Datasets http://research.google.com/pubs/pub36632.html "Interactive Analysis of Web-Scale Datasets http://research.google.com/pubs/pub36632.html").这个大数据查询利器的paper里面,其实主要也是在阐述底层文件存储格式。
Parquet支持复杂嵌套的数据结构组成,并使用重复级别/定义级别(repetition/definition level )的方法来对数据结构进行编码,嵌套的方式其实可以避免了大数据的join问题.
Parquet支持对某一列数据进行压缩,支持任意开发语言的读写操作.目前是apache的顶级项目.
parquet文件格式分析
首先来看一下如何定义一个parquet的文件格式,这里也是采用类似PB的格式定义 这里采用了班级信息来作为示例,有多个班级,每一个班级有个master,有多个学生(可以无),每个学生有名称和多个爱好,还有每一门可课程的成绩以及课程名称. schema定义: message classroom{ required string master; repeated group students{ required string name; repeated string hobbys; repeated group coursescore{ required string name; optional string score; } } }
required 表示必填 repeated 表示可以有任意个 optional 0 or 1 对于数据可以关系可以分为Map以及List,如果为List可以采用repeated,Map采用group 关键字修饰.
这里我们来定义一组数据:
{ master:"jack", student: name:"tom" student: name:"joy", hobbys:"basketball", hobbys:"football", coursescore: name:"math", coursescore: name:"chinese", score:100 } { master:"BoBo" }
两个班级一个有学生一个没有,一个学生有爱好有课程,一个什么也没有. 我们先来看看如何存储.
存储
依据上面定义的schema,可以先转化为一个tree表示结构
只有树的根节点是需要实际存储的数据节点,其余的只是关系的一种维系。 下图展示了其嵌套关系
实际存储也是这样,每一列存储了所有的数据信息。是不是存储很容易。
读取
既然所有的同一类的数据存储在一起,那么数据如何还原为原来的数据。这里引入了parquet的元数据信息,如何还原数据需要 Repetition Level以及Definition Level这两个元数据信息。
首先我们需要知道哪些数据是一组的,其实还需要知道数据和数据之间的层级关系,OK。这两个元数据信息可以帮我们搞的.(当然也是存储的时候写入的元数据信息)
Repetition Level是记录该列的值是在哪一个级别上重复的。
用刚才的两个classroom信息来举例: 对于两个classroom的master来说,由于都是独立的没有直接关系,所以他们的Repetition level是0
Jack 0
BoBO 0
对于jack的学生tom,joy来说,tom是第一个学生,所以level是0,而joy平级,所以是1.
master | Repetition Level |
Jack | 0 |
BoBo | 0 |
student.name | Repetition Level |
tom | 0 |
joy | 1 |
null | 2 |
student.coursescore.score | Repetition Level |
null | 0 |
null | 2 |
100 | 1 |
基于Repetition level是可以把原有的数据分好类,但是我们现在我们还不知道一条记录到什么位置STOP,以及数据之前的关系,这个时候在引入Definition Level。
这个时候在引入Definition Level 是定义的深度,用来记录该列是否是虚拟出来的。所以对于非NULL的记录,是没有意义的,其值必然为相同。同样举个例子。 比如对于master来说深度就是0,因为是required。
master | Definition Level |
Jack | 0 |
BoBo | 0 |
student.name | Definition Level |
tom | 1 |
joy | 2 |
null | 1 |