由于blog各种垃圾评论太多,而且本人审核评论周期较长,所以懒得管理评论了,就把评论功能关闭,有问题可以直接qq骚扰我

hive存储格式和压缩算法选择

大数据 西门飞冰 6646℃
[隐藏]

1.结论

hive 压缩和存储组合推荐使用:orc + snappy 获得最好的性能和合理的压缩率

1.1.存储格式选择

Hive支持的存储数据的格式主要有:textfile 、orc、parquet。

textfile存储格式是基于行存储的,实际生产不使用,一般只有数仓的ODS原始数据层使用。

orc和parquet是基于列式存储的,orc存储格式占用空间比parquet要小,且orc格式查询性能普遍比parquet格式高出10%~20%,所以生产一般选择使用orc格式存储

Parquet 主要使用场景在 Impala 和 Hive 共享数据和元数据的场景,因为orc不支持impala引擎。

1.2.压缩算法的选择

计算过程中压缩算法的选择,就比较耿直和直接,绝大多数场景就是谁压缩/解压快选择谁,因为在计算过程中过度追求数据的压缩率,会增加压缩的时间和CPU的占用,反而得不偿失

snappy 是目前最稳定的压缩算法,具有高速的压缩解压速度和合理的压缩率

ZLIB 压缩算法虽然是orc存储默认的压缩算法,压缩率也比snappy要好,但是因为压缩解压缩速度比较慢,所以不建议使用。

2.文件存储格式

Hive支持的存储数据的格式主要有:textfile 、orc、parquet。

2.1.列式存储和行式存储

image-20221004121533396

如图所示左边为逻辑表,右边第一个为行式存储(一行中的数据在存储介质中以连续存储形式存在),第二个为列式存储(一列中的数据在存储介质中以连续存储形式存在)。

1)行存储的特点

查询满足条件的一整行数据的时候,列存储则需要去每个聚集的字段找到对应的每个列的值,行存储只需要找到其中一个值,其余的值都在相邻地方,所以此时行存储查询的速度更快。

行式存储的适用场景包括:

1、适合随机的增删改查操作;

2、需要在行中选取所有属性的查询操作;

3、需要频繁插入或更新的操作,其操作与索引和行的大小更为相关。

4、行式数据库主要适合于在线交易性的OLTP应用

2)列存储的特点

因为每个字段的数据聚集存储,在查询只需要少数几个字段的时候,能大大减少读取的数据量;每个字段的数据类型一定是相同的,列式存储可以针对性的设计更好的设计压缩算法。

列式存储的适用场景包括:

1、查询过程中,可针对各列的运算并发执行(SMP),在内存中聚合完整记录集,可降低查询响应时间;

2、可在数据列中高效查找数据,无需维护索引(任何列都能作为索引),查询过程中能够尽量减少无关IO,避免全表扫描;

3、因为各列独立存储,且数据类型已知,可以针对该列的数据类型、数据量大小等因素动态选择压缩算法,以提高物理存储利用率;如果某一行的某一列没有数据,那在列存储时,就可以不存储该列的值,这将比行式存储更节省空间。

4、列式数据库主要适合于海量静态数据的分析,一般应用于OLAP

textfile的存储格式都是基于行存储的。

orc和parquet是基于列式存储的

2.2.TextFile格式

默认格式,数据不做压缩,磁盘开销大,数据解析开销大。可结合Gzip、Bzip2使用,但使用Gzip这种方式,Hive不会对数据进行切分,从而无法对数据进行并行操作。

2.3.Orc格式

如下图所示可以看到每个Orc文件由1个或多个stripe组成,每个stripe一般为HDFS的块大小,每一个stripe包含多条记录,这些记录按照列进行独立存储,对应到Parquet中的row group的概念。每个stripe里有三部分组成,分别是Index Data,Row Data,Stripe Footer。

image-20221004123019707

(1)Index Data:一个轻量级的index,默认是每隔1W行做一个索引。这里做的索引只是记录某行的各字段在Row Data中的offset。

(2)Row Data:存的是具体的数据,先取部分行,然后对这些行按列进行存储。对每个列进行了编码,分成多个Stream来存储。

(3)Stripe Footer:存的是各个Stream的类型,长度等信息。

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

2.4.Parquet格式

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

image-20221004123401401

(1)行组(Row Group):每一个行组包含一定的行数,在一个HDFS文件中至少存储一个行组,类似于orc的stripe的概念。

(2)列块(Column Chunk):在一个行组中每一列保存在一个列块中,行组中的所有列连续的存储在这个行组文件中。一个列块中的值都是相同类型的,不同的列块可能使用不同的算法进行压缩。

(3)页(Page):每一个列块划分为多个页,一个页是最小的编码的单位,在同一个列块的不同页可能使用不同的编码方式。

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

上图展示了一个Parquet文件的内容,一个文件中可以存储多个行组,文件的首位都是该文件的Magic Code,用于校验它是否是一个Parquet文件,Footer length记录了文件元数据的大小,通过该值和文件长度可以计算出元数据的偏移量,文件的元数据中包括每一个行组的元数据信息和该文件存储数据的Schema信息。除了文件中每一个行组的元数据,每一页的开始都会存储该页的元数据,在Parquet中,有三种类型的页:数据页、字典页和索引页。数据页用于存储当前行组中该列的值,字典页存储该列值的编码字典,每一个列块中最多包含一个字典页,索引页用来存储当前行组下该列的索引,目前Parquet中还不支持索引页。

3.压缩算法

3.1.压缩的好处和坏处

压缩的优点:以减少磁盘IO、节省磁盘存储空间。由于压缩后的数据占用的带宽更少,因此可以加快数据在Hadoop集群流动的速度。

压缩的缺点:Hive做大数据分析运行过程中,需要花费额外的时间/CPU做压缩和解压缩计算。

4.压缩和存储组合使用

创建一个snappy压缩的ORC存储方式

hive (default)> 
create table log_orc_snappy(
    id string,
    name string
)
row format delimited fields terminated by '\t'
stored as orc
tblproperties("orc.compress"="SNAPPY");

创建一个snappy压缩的parquet存储方式

create table log_parquet_snappy(
    id string,
    name string
)
row format delimited fields terminated by '\t'
stored as parquet
tblproperties("parquet.compression"="SNAPPY");

5.问题

网上描述:ORC文件支持Snappy压缩,但不支持lzo压缩,所以在实际生产中,使用Parquet存储 + lzo压缩的方式更为常见,这种情况下可以避免由于读取不可分割大文件引发的数据倾斜。

错误点:ORC+Snappy 不是对整体的数据集进行压缩,而是对ORC的每一个文件块进行压缩,所以不存在分割大文件的情况,具体可参考官方文档如下配置,默认262,144 bytes一个压缩块

https://cwiki.apache.org/confluence/display/Hive/LanguageManual+ORC

image-20221004163913347

转载请注明:西门飞冰的博客 » hive存储格式和压缩算法选择

喜欢 (1)or分享 (0)