打怪升级之小白的大数据之旅(六十八)<Hive旅程第九站:Hive的压缩与存储>

Posted GaryLea

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了打怪升级之小白的大数据之旅(六十八)<Hive旅程第九站:Hive的压缩与存储>相关的知识,希望对你有一定的参考价值。

打怪升级之小白的大数据之旅(六十八)

Hive旅程第九站:Hive的压缩与存储

上次回顾

  • 上一章,我们学习完了hive的函数相关操作,到此,我们hive的大的知识点就全部介绍完毕了,当然了,还有一些细节我没有讲到,大家可以私信我或者去官网看看说明文档:https://cwiki.apache.org/confluence/display/Hive/LanguageManual+ORC
  • 本章和下一章的内容与Hadoop学习一样,我将优化部分拆分成两块,把压缩和存储单独抽出来,然后再是其他在工作中遇到的一些优化方法总结,好了,进入正题

Hadoop压缩配置

  • 因为hive是基于Hadoop的,所以支持的压缩算法、编码等知识点我在Hadoop压缩那一章讲过了,这里就把具体的压缩参数配置再次回顾一下
  • 只有io.compression.codecs这个配置在core-site.xml中,其他的都在mapred-site.xml文件中
参数默认值阶段建议
io.compression.codecs (在core-site.xml中配置)org.apache.hadoop.io.compress.DefaultCodec, org.apache.hadoop.io.compress.GzipCodec, org.apache.hadoop.io.compress.BZip2Codec, org.apache.hadoop.io.compress.Lz4Codec输入压缩Hadoop使用文件扩展名判断是否支持某种编解码器
mapreduce.map.output.compressfalsemapper输出这个参数设为true启用压缩
mapreduce.map.output.compress.codecorg.apache.hadoop.io.compress.DefaultCodecmapper输出使用LZO、LZ4或snappy编解码器在此阶段压缩数据
mapreduce.output.fileoutputformat.compressfalsereducer输出这个参数设为true启用压缩
mapreduce.output.fileoutputformat.compress.codecorg.apache.hadoop.io.compress. DefaultCodecreducer输出使用标准工具或者编解码器,如gzip和bzip2
mapreduce.output.fileoutputformat.compress.typeRECORDreducer输出SequenceFile输出使用的压缩类型:NONE和BLOCK

Map输出阶段压缩

开启map输出阶段压缩可以减少job中map和Reduce task间数据传输量。具体配置如下

-- 直接在hive终端使用如下参数
-- 开启hive中间传输数据压缩功能
set hive.exec.compress.intermediate=true;
-- 开启mapreduce中map输出压缩功能
set mapreduce.map.output.compress=true;
-- 设置mapreduce中map输出数据的压缩方式
set mapreduce.map.output.compress.codec=org.apache.hadoop.io.compress.SnappyCodec;

Reduce输出阶段压缩

  • 当Hive将输出写入到表中时,输出内容同样可以进行压缩
  • 属性hive.exec.compress.output控制着这个功能
  • 用户可能需要保持默认设置文件中的默认值false,这样默认的输出就是非压缩的纯文本文件了
  • 用户可以通过在查询语句或执行脚本中设置这个值为true,来开启输出结果压缩功能
开启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支持的存储数据的格式主要有:TEXTFILE 、SEQUENCEFILE、ORC、PARQUET
  • 我们数据库中看到的数据是这个样子的
  • 实际上,这个是我们看到的样子,它是逻辑表,真正的存储还是如同数组一样…让我们来看看真正的存储样子是什么吧

行存储与列存储

下图中,左边为逻辑表,右边第一个为行式存储,第二个为列式存储

这下知道我们的表在真正存储时的样子了吧
row layout 对应的就是逻辑表中的一行数据 a1,b1,c1
column layout 对应的就是逻辑表中的一列数据 a1 a2 a3 a4 a5

行存储

  • 查询满足条件的一整行数据的时候,行存储只需要找到其中一个值,其余的值都在相邻地方,所以此时行存储查询的速度更快,就像上图中的row layout,我们要查询a1,b1,c1的时候,只需要找到a1,即可快速找到b1和c1

列存储

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

数据存储格式:

  • TextFile和SequenceFile的存储格式都是基于行存储的;
  • ORC和Parquet是基于列式存储的

TextFile格式

  • 还记得DDL操作中创建表时,sorted by 这个参数么,它就是用来指定文件的存储格式的,当我们不指定时,默认就是TextFile格式
  • TextFile特点是数据不做压缩,磁盘开销大,数据解析开销大。通常我们结合Gzip、Bzip2使用
  • 但是使用Gzip这种方式,hive不会对数据进行切分,从而无法对数据进行并行操作

Orc格式

  • 这个是我比较推荐的文件存储格式,它是Hive 0.11版里引入的新的存储格式

Orc格式存储原理

  • 每个Orc文件由1个或多个stripe组成,每个stripe一般为HDFS的块大小,每一个stripe包含多条记录,这些记录按照列进行独立存储,对应到Parquet中的row group的概念(下面会讲)

  • 每个Stripe里有三部分组成,分别是Index Data,Row Data,Stripe Footer

    • Index Data:一个轻量级的index,默认是每隔1W行做一个索引。这里做的索引应该只是记录某行的各字段在Row Data中的offset
    • Row Data:存的是具体的数据,先取部分行,然后对这些行按列进行存储。对每个列进行了编码,分成多个Stream来存储
    • Stripe Footer:存的是各个Stream的类型,长度等信息
  • 每个文件有一个File Footer,这里面存的是每个Stripe的行数,每个Column的数据类型信息等;

  • 每个文件的尾部是一个PostScript,这里面记录了整个文件的压缩类型以及FileFooter的长度信息等

  • 在读取文件时,会seek到文件尾部读PostScript,从里面解析到File Footer长度,再读FileFooter

  • 从里面解析到各个Stripe信息,再读各个Stripe,即从后往前读

Parquet格式

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

  • Parquet由三个部分组成

    • 行组(Row Group):每一个行组包含一定的行数,在一个HDFS文件中至少存储一个行组,类似于orc的stripe的概念
    • 列块(Column Chunk):在一个行组中每一列保存在一个列块中,行组中的所有列连续的存储在这个行组文件中。一个列块中的值都是相同类型的,不同的列块可能使用不同的算法进行压缩
    • 页(Page):每一个列块划分为多个页,一个页是最小的编码的单位,在同一个列块的不同页可能使用不同的编码方式
  • 通常情况下,在存储Parquet数据的时候会按照Block大小设置行组的大小

  • 由于一般情况下每一个Mapper任务处理数据的最小单位是一个Block,这样可以把每一个行组由一个Mapper任务处理,增大任务执行并行度

Parquet存储原理

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

指定文件格式示例

创建表,存储数据格式为TEXTFILE

create table log_text_file (
    id int
    name string)
row format delimited fields terminated by '\\t'
stored as textfile;

创建表,存储数据格式为ORC

create table log_orc_file(
    id int
    name string)
row format delimited fields terminated by '\\t'
stored as orc
tblproperties("orc.compress"="NONE"); -- 设置orc存储不使用压缩

创建表,存储数据格式为Parquet

create table log_parquet_file(
    id int
    name string)
row format delimited fields terminated by '\\t'
stored as parquet ;

通常情况下指定了文件存储格式,它们的大小比较如下(ORC存储大小最小):
ORC > Parquet > textFile

存储结合压缩

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

create table log_orc_zlib_file(
    id int
    name string)
row format delimited fields terminated by '\\t'
stored as orc
tblproperties("orc.compress"="ZLIB");

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

create table log_orc_snappy_file(
    id int
    name string)
row format delimited fields terminated by '\\t'
stored as orc
tblproperties("orc.compress"="SNAPPY");

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

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

存储方式和压缩总结

  • 在实际的项目开发当中,hive表的数据存储格式一般选择:orc或parquet。压缩方式一般选择snappy,lzo

总结

好了,压缩与存储的内容就这么多,下一章是Hive的其他优化

以上是关于打怪升级之小白的大数据之旅(六十八)<Hive旅程第九站:Hive的压缩与存储>的主要内容,如果未能解决你的问题,请参考以下文章

打怪升级之小白的大数据之旅(六十)<Hive旅程中的始发站>

打怪升级之小白的大数据之旅(六十)<Hive旅程中的始发站>

打怪升级之小白的大数据之旅(六十一)<Hive旅程第二站:Hive安装>

打怪升级之小白的大数据之旅(六十一)<Hive旅程第二站:Hive安装>

打怪升级之小白的大数据之旅(六十二)<Hive旅程第三站:Hive数据类型>

打怪升级之小白的大数据之旅(六十二)<Hive旅程第三站:Hive数据类型>