Hive 存储格式和压缩算法

存储格式

行式存储和列式存储

行式存储的优点:查询满足条件的一整行数据时,行式存储的数据查询更快。因为行存储只需要找到其中一个值,其余的值都在相的邻地方,而列式存储则需要去每个聚集的字段找到对应的每列的值。

列式存储的优点:查询满足条件的一整列数据时,列式存储的数据查询更快。因为列存储只需要找到其中一个值,其余的值都在相邻的地方,而行存储则需要去每个聚集的字段找到对应的每个行的值。另一方面,列式存储更便于针对性的设计更好的压缩算法,因为每个字段的数据类型一定是相同的。

常见存储格式

TextFile

TextFile是 Hive 默认的文件格式,属于行式存储。默认数据不做压缩,占用磁盘空间大。 可以结合Gzip、Bzip2进行压缩,Hive 执行查询时会自动解压。使用这种方式压缩的缺点是,Hive不会对数据进行切分, 从而无法对数据进行并行处理。

API:

org.apache.hadoop.mapred.TextInputFormat
org.apache.hive.ql.io.HiveIgnoreKeyTextOutputFormat

建表语句:

create table if not exists textfile_table(
    …
)
row format delimited fields terminated by ‘\t’
stored as textfile;

SequenceFile

SequenceFile是Hadoop API提供的一种二进制文件格式,属于行式存储,具有可分割、可压缩的特点。 SequenceFile格式直接将数据序列化并压缩文件中,所以其文件不能直接查看,可以放在 HDFS 通过hadoop fs -text命令查看。另外,SequenceFile 文件也不支持追加写入。

SequenceFile支持三种压缩选择:

  • NONE:不压缩
  • RECORD:压缩率低
  • BLOCK:压缩率高,一般建议使用BLOCK压缩

API

org.apache.hadoop.mapred.SequenceFileInputFormat
org.apache.hadoop.hive.ql.io.HiveSequenceFileOutputFormat

建表语句

create table if not exists seqfile_table(
    …
)
row format delimited fields terminated by ‘\t’
stored as sequencefile;

RcFile

RcFile是一种行列存储相结合的文件格式。首先,其将数据按行分块,保证同一个记录在一个块上,避免读一个记录需要读取多个块。然后,块数据列式存储,有利于数据压缩和快速的列存取。

相比TextFile和SequenceFile,RcFile由于列式存储特性,数据加载时性能消耗较大,但是具有较好的压缩比和查询响应。数据仓库的特点是一次写入、多次读取,因此,相比之下,RcFile更有优势。

API

org.apache.hadoop.hive.ql.io.RCFileInputFormat
org.apache.hadoop.hive.ql.io.RCFileOutputFormat

建表语句:

create table if not exists rcfile_table(
    …
)
row format delimited fields terminated by ‘\t’
stored as rcfile;

OrcFile

OrcFile 在 Hadoop 0.11 版本后出现,是RcFile的优化,可以提高hive的读写和处理性能,并提供更高的压缩效率,是目前主流选择之一。

如图所示,每个Orc文件由1个或多个stripe组成,每个stripe250MB大小,这个Stripe实际相当于RowGroup概念,不过大小由4MB至250MB不等,这样能提升顺序读的吞吐率。每个Stripe里有三部分组成,分别是Index Data,Row Data,Stripe Footer:

  • Index Data:一个轻量级的index,默认是每隔1W行做一个索引。这里做的索引只是记录某行的各字段在Row Data中的offset。
  • Row Data:存的是具体的数据,先取部分行,然后对这些行按列进行存储。对每个列进行了编码,分成多个Stream来存储。
  • StripFooter:Stripe Footer:存的是各个stripe的元数据信息。

另外,每个文件有一个File Footer,这里面存的是每个Stripe的行数,每个Column的数据类型信息等;每个文件的尾部是一个PostScript,这里面记录了整个文件的压缩类型以及FileFooter的长度信息等。在读取文件时,会seek到文件尾部读PostScript,从里面解析到File Footer长度,再读FileFooter,从里面解析到各个Stripe信息,再读各个Stripe,即从后往前读。

Parquet

Parquet是面向分析型业务的列式存储格式,由Twitter和Cloudera合作开发,2015年5月从Apache的孵化器里毕业成为Apache顶级项目。

Parquet文件是以二进制方式存储的,所以是不可以直接读取的,文件中包括该文件的数据和元数据,因此Parquet格式文件是自解析的。

通常情况下,在存储Parquet数据的时候会按照Block大小设置行组的大小,由于一般情况下每一个Mapper任务处理数据的最小单位是一个Block,这样可以把每一个行组由一个Mapper任务处理,增大任务执行并行度。

Parquet格式具备对其他 Hadoop的可移植性,包括Hive, Drill, Impala, Crunch, and Pig。

API

org.apache.hadoop.hive.ql.io.parquet.MapredParquetInputFormat
org.apache.hadoop.hive.ql.io.parquet.MapredParquetOutputFormat

Avro

Avro是一个数据序列化系统,设计用于支持大批量数据交换的应用。它的主要特点有:支持二进制序列化方式,可以便捷,快速地处理大量数据。

Avro对动态语言友好,Avro提供的机制使动态语言可以方便地处理Avro数据。

API

org.apache.hadoop.hive.ql.io.avro.AvroContainerInputFormat
org.apache.hadoop.hive.ql.io.avro.AvroContainerOutputFormat

存储格式和数据导入

除了TextFile 格式,其他格式如SequenceFile,OrcFile等格式的表不能直接从本地文件导入数据(Load Data)。数据要先导入到TextFile格式的表中, 然后再用insert select 语句导入到SequenceFile、ORCFile等格式的表中。

压缩算法

数据压缩的优缺点

  • 优点:减少空间占用,降低单节点的磁盘IO,提升传输速度。
  • 缺点:读取、写入时需要花费额外的资源做压缩和解压缩计算。

压缩算法评价

  • 压缩比: 越高越好,以减少空间消耗;
  • 压缩时间:越快越好,减少时间消耗;
  • 压缩后文件是否可分割:最好支持,这样一个文件可以有多个 Mapper 并行处理,提高速度 ;

常见压缩算法

 

压缩方式

压缩比

压缩速度

解缩速度

是否可分割

Gzip

13.4%

21 MB/s

118 MB/s

BZip2

13.2%

2.4MB/s

9.5MB/s

LZO

20.5%

135 MB/s

410 MB/s

LZ4

   

Snappy

22.2%

172 MB/s

409 MB/s

 

常见编码/解码器

 

压缩格式

对应的编码/解码器

Gzip

org.apache.hadoop.io.compress.GzipCodec

BZip2

org.apache.hadoop.io.compress.BZip2Codec

LZO

com.hadoop.compress.lzo.LzopCodec

Lz4

org.apache.hadoop.io.compress.Lz4Codec

Snappy

org.apache.hadoop.io.compress.SnappyCodec

 

开启Map输出阶段压缩

开启Map输出阶段压缩,是指在MapReduce的shuffle阶段对mapper产生的中间结果数据压缩,可以减少Job中Map和Reduce任务间数据传输量。这个阶段应优先选择一个低CPU开销的算法。

控制这一功能的激活与禁用的参数为 hive.exec.compress.intermediate,默认为 false。

具体语句:

开启hive中间传输数据压缩功能
set hive.exec.compress.intermediate=true;
开启mapreducemap输出压缩功能
set mapreduce.map.output.compress=true;
设置mapreducemap输出数据的压缩方式
set mapreduce.map.output.compress.codec= org.apache.hadoop.io.compress.SnappyCodec;
设置mapreducemap输出数据的压缩为块压缩
set hive.intermediate.compression.type=BLOCK;

开启Reduce输出阶段压缩

开启Reduce输出阶段压缩,可以减少到各组MapReduce 任务之间的数据传输量,并令最终输出Hive 表的数据也经过压缩。

控制这一功能的激活与禁用的参数为 hive.exec.compress.output,默认为 false。

具体语句:

开启hive最终输出数据压缩功能
set hive.exec.compress.output=true;
开启mapreduce最终输出数据压缩
set mapreduce.output.fileoutputformat.compress=true;
设置mapreduce最终数据输出压缩算法
set mapreduce.output.fileoutputformat.compress.codec = org.apache.hadoop.io.compress.SnappyCodec;
设置mapreduce最终数据输出压缩为块压缩
set mapreduce.output.fileoutputformat.compress.type=BLOCK;

存储和压缩结合

要实现 Hive 表数据压缩,可以在插入数据之前,设置前面提到的压缩相关参数。同时,我们也可以在建表的时候,设置表的相关属性来指定压缩算法和参数,这样插入数据时的时候会自动应用表属性里的压缩配置。

以 Orc 格式为例,Orc 有以下压缩相关的属性:

Key

Default

Notes

orc.compress

ZLIB

high level compression (one of NONE, ZLIB, SNAPPY)

orc.compress.size

262,144

number of bytes in each compression chunk

orc.stripe.size

67,108,864

number of bytes in each stripe

orc.row.index.stride

10,000

number of rows between index entries (must be >= 1000)

orc.create.index

true

whether to create row indexes

orc.bloom.filter.columns

“”

comma separated list of column names for which bloom filter should be created

orc.bloom.filter.fpp

0.05

false positive probability for bloom filter (must >0.0 and <1.0)

当要创建一个SNAPPY压缩的ORC存储格式时,使用建表语句的 tblproperties 来设置:

CREATE TABLE orc_snappy(
    …
)
ROW FORMAT DELIMITED FIELDS TERMINATED BY ‘\t’
STORED AS orc
tblproperties (“orc.compress”=“SNAPPY”);

或者在建表语句之前,使用 set 命令设置:

set orc.compress=SNAPPY;
CREATE TABLE orc_snappy(
    …
)
ROW FORMAT DELIMITED FIELDS TERMINATED BY ‘\t’
STORED AS orc;

存储格式和压缩格式如何选择

1. 大数据量情况下使用支持分割的压缩格式

若压缩文件不支持分割,那么这个文件只能被一个 Map任务读取。如果该压缩文件很大,那么处理该文件的Map需要花费的时间会远多于读取普通文件的Map时间,这就是常说的Map读取文件的数据倾斜。

要避免这种情况的发生,就需要在数据压缩的时候采用bzip2和Zip等支持文件分割的压缩算法。然而 Orc格式恰恰不支持这些压缩方式,所以这也是大家在遇到大数据量的情况下不选择 Orc的原因。

在数据量较大的情况下,可以使用Parquet存储+ LZO压缩,可以避免由于读取不可分割大文件导致的数据倾斜。

若数据量不大(10 GB以下),ORC存储 + Snappy压缩的效率还是非常高的,可以整体提升Hive的执行速度。

2. 接口表使用TextFile等文本格式

接口表指数据源从外部加载,或者数据需要导出到外部的表。接口表不建议使用 ORC 等格式。

对于加载外部数据的场景:由于文本格式到ORC,需要耗费较高的CPU计算资源,相比于直接落地成文本格式Hive表而言加载性能会低很多;

对于Hive表作为计算结果,导出给外部使用的场景:ORC格式的结果数据,相比于文本格式的结果数据而言其易读性低很多。

KAMI
KAMI
数据挖掘研究员,专注分享数据领域的技术和业务,以及逻辑、思维和方法论

发表回复

文章结构
相关文章