文章目录
大数据中常见的几种文件格式
Ⅰ.TextFile文件
01文件格式:
文件存储展示为正常的文本文件,也就是我们普通的windows上的txt后缀文件。可以存储一些简单的文本数据。我们可以下载文件后直接打开查看,也可以在HDFS上可以使用hadoop命令##“hdfs dfs -cat 【filename】”去查看当前数据。
02如何建表
hive中如果不指定表的格式,那么默认就是textfile格式
create table myText{
id int,
name string
)
partitioned by (ds string)
row format delimited terminal by "\t"
stored as textfile;
03格式评估
优点:
- 使用行存储,一行就是一条记录。方便查看,偏于理解数据存储;
- 可以使用用户自定义的分隔符进行分割数据【一般企业中使用的分割符时使用一些不常见字符,可以防止因为分隔符切割字段时发现字段值内包含分隔符导致数据错误发生】
缺点:
- 没有压缩机制。存储占用空间较大。可以结合其他压缩方式【snappy,bzip2,gzip,lzo】进行压缩。如果使用一些压缩方式的话,处理数据时会因为数据无法被切割,所以导致无法并行运行。效率会降低。
Ⅱ.SequenceFile文件
01文件格式
下文将SequencrFile文件简称为SF文件。
SF文件格式是用以key-value形式存储数据。文件中的数据是按照二进制格式来进行编码的,无法直接查看数据。下载到本地之后也是二进制文件。无法可视化。自带一定的压缩机制【none,record,block】
02如何建表
create table myText{
id int,
name string
)
partitioned by (ds string)
row format delimited terminal by "\t"
stored as sequencefile;
03数据存储结构
结构组成
- header
- record【若干】
- sync【可以理解为是一个位点。作为文件位置的标识,定位功能】
结构介绍
- header中存储【magic number,file header,sync】
magic number:标识这是一个SF文件
file header:存储当前key,value的类信息,压缩类型,数据的元信息 - record存储【key和value的值,以及key和value的长度】:
RecordLen-KeyLen-Key-Val·····若干
压缩j机制
- none:不采取压缩机制
- record:将value使用压缩机制
- block:key和value都使用压缩机制
04格式评估
优点:
- 可以存储key-value的数据,方便mapreduce进行查询,也可以合并小文件,可作为小文件容器;
- 自带压缩方式,比起text文件来说更节省磁盘空间;
- 可切割,数据可以并行处理,提高效率;
缺点:
- 基于行存储,查询效率受限
- 数据以二进制格式存在,无法进行查看数据,无法可视化数据
Ⅱ.Parquet文件
导引:一般数据都是基于行存储来实现,比如oracle,mysql,text文件。但是后来文件数量骤增。查询速度与效率急需改进。但是行查询避免不了全表扫描。此时需要出现一种文件格式,可以避免全表扫描,但是可以处理复杂数据格式。所以出现了面向列存储的文件格式。
01文件格式
parquet文件是面向列存储的。它没有复杂的数据结构【map,list··】,而是使用自己的field属性定义来实现了类似复杂结构的嵌套模式。
①字段组成:
每个字段有三部分组成:重复数【required(出现有且只有一次),repeated(出现0次或多次),optional(出现0次或1次)】
举个栗子:
message Document {
required int64 DocId;
optional group Links {
repeated int64 Backward;
repeated int64 Forward;
}
repeated group Name {
repeated group Language {
required string Code;
optional string Country;
}
optional string Url;
}
}
我们可以将上图转为一棵树:
栗子分析:
字段名 | 重复性 | 描述 |
---|---|---|
docid | required | 每条记录中都必须有且仅有一个docid |
backward | repeated | 每条记录可以没有backward,或者有多个backward |
forward | repeated | 每条记录可以没有forward,或者有多个forward |
language | repeated | 每条记录可以没有language,或者有多个language |
code | repeated | 如果language不为空的话,那么一定有code字段。如果language为空。code可以为空 |
country | repeated | 每条记录可以没有country,有的话只能出现一个country |
url | repeated | 每条记录可以没有url,有的话只能出现一个url |
②存储分析
==我们会发现在一条记录中有些字段是可以重复的。那么如何在底层进行相关存储的呢?
这里使用的Striping/Assembly算法 【拆开-合并算法】。此算法显式表现为三个值。
1.value【字段本身值】
2.definition level【从根节点(第0层)遍历每一个叶子节点,当叶子节点filed为空是,当前遍历路径的深度(不算叶子为空的那个节点),此值不对required类型进行计算,因为required类型不可能为空。只要父节点有值,那么required一定有且仅有一个值】
作用:field为空的字段底层会设置占位符,为了防止两条记录因为没有占位符而产生数据交错发生。
3.repetition level【标识当前filed和上一个重复字段value是在哪一层不共享的。如果是0代表就是一条新的记录,因为从根节点就不共享了,那么一定是两条独立的记录】
③实际存储
给定数据:
record1:
record2:
这里有两条记录,我们来分析下,这两条数据如何存储到磁盘中:
==首先明确数据按列存储,所以我们分析的时候直接按列分析
1)docid:
record1:类型为required,所以definition【下文简称D】是不需要的,D=0,repetition【下文简称R】,这是记录的第一条,而且一条记录有且仅有一个docid。所以R=0
record2:类型为required,D同上,D=0,对于记录二来说,docid依旧有且只有一条,所以R=0
value | Definition | repetition |
---|---|---|
10 | 0 | 0 |
20 | 0 | 0 |
2)backward:
record1:类型为repeated,record1中backward为空,那么当前路径下最大深度就root【根】–>links,因为根是从0开始计算。links是第一层。也就是D=1。至于R,因为类型是repeated,当前backward是出现的第一次(哪怕位空值),那么也代表一条新的记录。所以R=0。
record2:类型为repeated,有两条backward。重复次数为2。此时的D为root【根】–>links–>backward,所以D= 2.因为重复了三次backward,第一个backward的R,代表是一条新记录,第二个backward依旧属于当前记录,所以R=1
value | Definition | repetition |
---|---|---|
NULL | 1 | 0 |
10 | 2 | 0 |
30 | 2 | 2 |
3)forward:
推理和backward基本上是一致的
value | Definition | repetition |
---|---|---|
20 | 2 | 0 |
40 | 2 | 2 |
60 | 2 | 2 |
80 | 2 | 0 |
4)code
value | Definition | repetition |
---|---|---|
en-us | 2 | 0 |
en | 2 | 2 |
NULL | 1 | 1 |
en-gb | 2 | 1 |
NULL | 1 | 0 |
因为required如果父节点存在的话,required子节点一定存在,所以这个D值取父节点repeated最大深度即可。这样可以减少D最大值,方便存储。
另外我们看下code的R值。
01.code = ‘en-us’。是第一个出现的code值。所以为0
02.code = ‘en’,第二个出现的值,和上一值en-us在name节点共享,在language节点 不共享,所以R=2
03.code = null,第三个出现的值,和第二个值en在name节点不共享,所以R=1
04.code = en-gb,和第三个出现的值在name节点不共享,所以R=1
05.code = NULL,是记录2中首次出现,所以R=0
5)country
value | Definition | repetition |
---|---|---|
us | 3 | 0 |
NULL | 2 | 2 |
NULL | 1 | 1 |
gb | 3 | 1 |
NULL | 1 | 0 |
④提取数据
我们已经按照parquet的striping/assembly算法将数据写到磁盘了。那么下面我们如何将数据提取出来,并按照原先格式进行处理呢~
继续举个栗子:
我们这里就假设读取两个列字段吧。docid,forward
01我们读取第一行,R=0,D=0,VALUE = 10
r=0,代表这是新的一条记录,我们可以根据schema建立一个嵌套结构直到D=0,然后在下面建立一个docid字段,赋值为10
02读取第二行,R=0代表还是新记录,同上。
01.读取第一行
:r=0代表是一条新记录,之后扩展深度为2,将此时节点设置为forward,value赋值20
02读取第二行
:r=2,代表是在二层节点上不共享空间,所以需要另外建立一个二层节点forward,value赋值40
03读取第三行
:r=2,代表是在二层节点上不共享空间,所以需要另外建立一个二层节点forward,value赋值60
04读取第四行
:r=0代表是一条新记录,之后扩展深度为2,将此时节点设置为forward,value赋值80
02存储结构
parquet文件有以下几部分组成:【row group;column chunk;page;】
粗略制图,请多担待
04如何建表
==parquet和hive格式对应关系
BINARY -> STRING
BOOLEAN -> BOOLEAN
DOUBLE -> DOUBLE
FLOAT -> FLOAT
INT32 -> INT
INT64 -> BIGINT
INT96 -> TIMESTAMP
BINARY + OriginalType UTF8 -> STRING
BINARY + OriginalType DECIMAL -> DECIMAL
create table myText{
id int,
name string
)
partitioned by (ds string)
row format delimited terminal by "\t"
stored as parquet;
04格式评估
优点
- 最突出的优点是可以按照列式查询字段,省去了不必要的IO浪费。避免扫描全表
- 谓词下推,在存储column chunk时,会存储当前列的一些聚合指标,最大值,最小值,空值个数等。可以过滤一些不符合条件的rowgroup。提高了查询效率。
- 按照列来存储,可以按照每列的数据格式采取对应的压缩格式,因为每列数据类型一致,所以压缩性能更高。
缺点
- 文件是二进制格式,无法进行可视化查询
Ⅲ.RCFile文件
01.文件格式
rcfile文件其实也是基于列存储,和parquet整体存储格式是类似的。
02.数据存储
01首先会将表分为几个row group组,默认是4M一个row group。
02之后将组内的数据按照列切分出来,按列存储。
总体来讲,先按照横向切割,在按照纵向切割。切割之后进行存储数据。
从上图可以看出,底层是将每一列当成每一行进行连续存储在一起。
每个group除包含数据之外,另外还有sync作为位点。还有元数据头信息,保存当前group的数据行数,大小,字段详情信息。
03.如何建表
create table myText{
id int,
name string
)
partitioned by (ds string)
row format delimited terminal by "\t"
stored as rcfile;
注意:不可以直接导入rcfile文件,需要先导入text文件,之后将text文件导入到指定表中
1、先把TXT导Hive表中tbtxt
2、INSERT OVERWRITE table myTextSELECT * from tbtxt ;
04.格式评估
优点:
- 作为数据存储,使用了游程编码,也就是对于某一列来讲,不会存储重复的数据。这样就节省了不少空间。【我所在企业使用的是类似这种格式,在数据存储方面,一般会将比较大的列,进行排序存储。这样可以节省空间】
- 基于列式存储,避免全表扫描,提高查询效率
- 懒加载,只有在查询数据的时候,才会对该列进行解压缩。否则不一般不会操作该列数据。
缺点:
- 基于二进制文件格式,无法可视化
Ⅳ.ORC文件
01.文件格式
orc文件也是基于列进行存储,使用二进制存储文件。可以理解为是在RCFile的基础上记性了一些优化。具体优化在下面数据存储方面。orc支持hive的复杂map list结构,可以实现较为复杂的嵌套结构;
02.数据存储
我们可以发现,在存储结构中,比RCfile多出了一些部分。如stripe,footer。
01:首先会将表分为多个stripe,和rowgroup不同的是,这个stripe的大小为256M,而gruop为4M,从数据读取效率来讲,stripe更加高效。一次性读取的数据多了。省去反复读取的时间;stripe内部是按照row group进行分块的(每一个row group中多少条记录在文件的Footer中存储),row group内部按列存储。
02:postscript存储了当前文件的元数据信息,表行数,压缩参数,压缩大小,以及列信息
03:stripe footer:存储了当前stripe的一些统计指标,类似parquet中row group的一些聚合指标。
04:file footer:存储了每个stripe 的一些信息,位置等
05:indexdata:存储当前stripe下的数据索引信息
06:row data:具体的数据存储
03.如何建表
create table myText{
id int,
name string
)
partitioned by (ds string)
row format delimited terminal by "\t"
stored as orc;
注意:不可以直接导入orc文件,需要先导入text文件,之后将text文件导入到指定表中
1、先把TXT导Hive表中tbtxt
2、INSERT OVERWRITE table myTextSELECT * from tbtxt ;
04.数据读取
01:我们首先读取file footer获取每个stripe的位置信息
02:找到该stripe,读取indexdata索引信息,读取数据
05.格式评估
优点
- 加入了索引信息,读取数据更为高效
- 游程编码,节省空间
- 列式存储,查询速度高效
缺点
- 二进制格式,无法可视化