博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
大数据存储格式-parquet
阅读量:6932 次
发布时间:2019-06-27

本文共 3517 字,大约阅读时间需要 11 分钟。

hot3.png

大数据存储格式-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的格式如下: <code> access_log{ string ip; string access_time; ............(其他N个属性)

} </code>

如果是行存储:

我们需要读取一行的所有数据,然后获取其中的ip字段,在做分组统计。增加的磁盘的IO,同时也增加了计算压力.

如果是列存储会如何:

对于上面的统计,我们只需要读取IP就可以,读取不需要的列信息,这就是列存储对于大数据的统计类查询的优点所在,当然除此之外大数据本身的稀疏性,采用列式可能更好的去优化存储结构,减少存储空间.

parquet介绍

parquet是twitter在2013年开源的数据结构,google的Dremel: [Interactive Analysis of Web-Scale Datasets ](Interactive Analysis of Web-Scale Datasets "Interactive Analysis of Web-Scale Datasets ").这个大数据查询利器的paper里面,其实主要也是在阐述底层文件存储格式。

Parquet支持复杂嵌套的数据结构组成,并使用重复级别/定义级别(repetition/definition level )的方法来对数据结构进行编码,嵌套的方式其实可以避免了大数据的join问题.

Parquet支持对某一列数据进行压缩,支持任意开发语言的读写操作.目前是apache的顶级项目.

parquet文件格式分析

首先来看一下如何定义一个parquet的文件格式,这里也是采用类似PB的格式定义 这里采用了班级信息来作为示例,有多个班级,每一个班级有个master,有多个学生(可以无),每个学生有名称和多个爱好,还有每一门可课程的成绩以及课程名称. schema定义: <code> message classroom{ required string master; repeated group students{ required string name; repeated string hobbys; repeated group coursescore{ required string name; optional string score; } } } </code> required 表示必填 repeated 表示可以有任意个 optional 0 or 1 对于数据可以关系可以分为Map以及List,如果为List可以采用repeated,Map采用group 关键字修饰.

这里我们来定义一组数据:

<code> { master:"jack", student: name:"tom" student: name:"joy", hobbys:"basketball", hobbys:"football", coursescore: name:"math", coursescore: name:"chinese", score:100 } { master:"BoBo" } </code>

两个班级一个有学生一个没有,一个学生有爱好有课程,一个什么也没有. 我们先来看看如何存储.

存储

依据上面定义的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.

<table> <tr><td>master</td><td>Repetition Level</td><tr> <tr><td>Jack</td><td>0</td><tr> <tr><td>BoBo</td><td>0</td><tr> </table>

<table> <tr><td>student.name</td><td>Repetition Level</td><tr> <tr><td>tom</td><td>0</td><tr> <tr><td>joy</td><td>1</td><tr> <tr><td>null</td><td>2</td><tr> </table>

<table> <tr><td>student.coursescore.score</td><td>Repetition Level</td><tr> <tr><td>null</td><td>0</td><tr> <tr><td>null</td><td>2</td><tr> <tr><td>100</td><td>1</td><tr> </table>

基于Repetition level是可以把原有的数据分好类,但是我们现在我们还不知道一条记录到什么位置STOP,以及数据之前的关系,这个时候在引入Definition Level。

这个时候在引入Definition Level 是定义的深度,用来记录该列是否是虚拟出来的。所以对于非NULL的记录,是没有意义的,其值必然为相同。同样举个例子。 比如对于master来说深度就是0,因为是required。

<table> <tr><td>master</td><td>Definition Level</td><tr> <tr><td>Jack</td><td>0</td><tr> <tr><td>BoBo</td><td>0</td><tr> </table>

<table> <tr><td>student.name</td><td>Definition Level</td><tr> <tr><td>tom</td><td>1</td><tr> <tr><td>joy</td><td>2</td><tr> <tr><td>null</td><td>1</td><tr> <table> 通过Definition Level可以还原数据的嵌套关系。

其他

parquet已经有hive,pig,spark,impala等数据处理框架的支持,同时也是spark建议parquet作为其存储格式。通过以上可以看出,如果数据schema是扁平结构,那么其实,repetition level 和 definition level 就完全不需要。后续会继续写一些数据处理引擎的文档。

转载于:https://my.oschina.net/hadooper/blog/508765

你可能感兴趣的文章
线性表17 - 数据结构和算法22
查看>>
1. 38译码器
查看>>
什么是拉电流,什么是灌电流?什么是吸收电流 ?
查看>>
使用getScript()方法异步加载并执行js文件
查看>>
IDEA 学习笔记之 Scala项目开发
查看>>
Spring的IOC和AOP
查看>>
Linux 技巧:让进程在后台可靠运行的几种方法(转)
查看>>
redux和mobx比较(一)
查看>>
AC自动机习题集
查看>>
【转】Advanced Vi Cheat Sheet
查看>>
TCP/IP的网际层协议——ARP
查看>>
vue-搜索页-搜索历史本地存储-good-storage
查看>>
mysql操作
查看>>
shell脚本学习(四)
查看>>
identifier is too long 异常处理
查看>>
UVALive - 3266 Tian Ji -- The Horse Racing(贪心)
查看>>
单利运算1
查看>>
C++之运算符重载(前置++和后置++)
查看>>
linux快捷键
查看>>
android 操作文件
查看>>