Hive性能优化之表数据优化


1 文件格式

1.1 概述

Hive数据存储的本质还是HDFS,所有的数据读写都基于HDFS的文件来实现,为了提高对HDFS
文件读写的性能,Hive中提供了多种文件存储格式:TextFile、SequenceFile、RCFile、ORC、Parquet
等。不同的文件存储格式具有不同的存储特点,有的可以降低存储空间,有的可以提高查询性能等,
可以用来实现不同场景下的数据存储,以提高对于数据文件的读写效率。
在这里插入图片描述
下面为大家介绍常用的几种文件格式以及各自使用的场景。

1.2 TextFile

TextFIle是Hive中默认的文件格式,存储形式为按行存储。工作中最常见的数据文件格式就是
TextFile文件,几乎所有的原始数据生成都是TextFile格式,所以Hive设计时考虑到为了避免各种编
码及数据错乱的问题,选用了TextFile作为默认的格式。建表时不指定存储格式即为textfile,导入
数据时把数据文件拷贝至hdfs不进行处理。
⚫ TextFile的优点
◼ 最简单的数据格式,不需要经过处理,可以直接cat查看
◼ 可以使用任意的分隔符进行分割
◼ 便于和其他工具(Pig, grep, sed, awk)共享数据
◼ 可以搭配Gzip、Bzip2、Snappy等压缩一起使用
⚫ TextFile的缺点
◼ 耗费存储空间,I/O性能较低
◼ 结合压缩时Hive不进行数据切分合并,不能进行并行操作,查询效率低
◼ 按行存储,读取列的性能差
⚫ TextFile的应用场景
◼ 适合于小量数据的存储查询
◼ 一般用于做第一层数据加载和测试使用
⚫ TextFile的使用
◼ 创建原始数据表

-- 创建数据库
create database if not exists db_fileformat;
use db_fileformat;
-- 创建原始数据表
create table tb_sogou_source(
stime string,
userid string,
keyword string,
clickorder string,
url string
)
row format delimited fields terminated by ' '\t' ';

◼ 加载原始数据

load data local inpath '/export/data/SogouQ.reduced' into table
tb_sogou_source;

在这里插入图片描述
◼ 创建TextFile数据表

--创建 textfile 数据表
create table tb_sogou_text(
stime string,
userid string,
keyword string,
clickorder string,
url string
)
row format delimited fields terminated by ' '\t' '
stored as textfile;

◼ 写入TextFile数据表

insert into table tb_sogou_text
select * from tb_sogou_source;

在这里插入图片描述

1.3 SequenceFile

SequenceFile是Hadoop里用来存储序列化的键值对即二进制的一种文件格式。SequenceFile
文件也可以作为MapReduce作业的输入和输出,hive也支持这种格式。
⚫ SequenceFIle的优点
◼ 以二进制的KV形式存储数据,与底层交互更加友好,性能更快
◼ 可压缩、可分割,优化磁盘利用率和I/O
◼ 可并行操作数据,查询效率高
◼ SequenceFile也可以用于存储多个小文件
⚫ SequenceFIle的缺点
◼ 存储空间消耗最大
◼ 与非Hadoop生态系统之外的工具不兼容
◼ 构建SequenceFile需要通过TextFile文件转化加载。
⚫ SequenceFIle的应用
◼ 适合于小量数据,但是查询列比较多的场景
⚫ SequenceFIle的使用
◼ 创建SequenceFile数据表

create table tb_sogou_seq(
stime string,
userid string,
keyword string,
clickorder string,
url string
)
row format delimited fields terminated by ' '\t' '
stored as sequencefile;

◼ 写入SequenceFile数据表
insert into table tb_sogou_seq
select * from tb_sogou_source;
◼ 查看数据
在这里插入图片描述

1.4 Parquet

Parquet是一种支持嵌套结构的列式存储文件格式,最早是由Twitter和Cloudera合作开发,
2015年5月从Apache孵化器里毕业成为Apache顶级项目。是一种支持嵌套数据模型对的列式存储
系统,作为大数据系统中OLAP查询的优化方案,它已经被多种查询引擎原生支持,并且部分高性
能引擎将其作为默认的文件存储格式。通过数据编码和压缩,以及映射下推和谓词下推功能,
Parquet的性能也较之其它文件格式有所提升。
Parquet 是与语言无关的,而且不与任何一种数据处理框架绑定在一起,适配多种语言和组件,
能够与 Parquet 适配的查询引擎包括 Hive, Impala, Pig, Presto, Drill, Tajo, HAWQ, IBM Big SQL
等,计算框架包括 MapReduce, Spark, Cascading, Crunch, Scalding, Kite 等
Parquet是Hadoop生态圈中主流的列式存储格式,并且行业内流行这样一句话流传:如果说
HDFS是大数据时代文件系统的事实标准,Parquet 就是大数据时代存储格式的事实标准。Hive中
也同样支持使用Parquet格式来实现数据的存储,并且是工作中主要使用的存储格式之一。
⚫ Parquet的优点
◼ 更高效的压缩和编码
在这里插入图片描述
◼ 可用于多种数据处理框架
在这里插入图片描述
在这里插入图片描述
⚫ Parquet的缺点
◼ 不支持update, insert, delete, ACID
⚫ Parquet的应用
◼ 适用于字段数非常多,无更新,只取部分列的查询。
⚫ Parquet的使用
◼ 创建Parquet数据表

create table tb_sogou_parquet(
stime string,
userid string,
keyword string,
clickorder string,
url string
)
row format delimited fields terminated by ' '\t' '
stored as parquet;

◼ 写入Parquet数据表

insert into table tb_sogou_parquet
select * from tb_sogou_source;

◼ 查看数据
在这里插入图片描述

1.5 ORC

ORC(OptimizedRC File)文件格式也是一种Hadoop生态圈中的列式存储格式,源自于RC
(RecordColumnar File),它的产生早在2013年初,最初产生自Apache Hive,用于降低Hadoop
数据存储空间和加速Hive查询速度。它并不是一个单纯的列式存储格式,仍然是首先根据行组分割
整个表,在每一个行组内进行按列存储。ORC文件是自描述的,它的元数据使用Protocol Buffers
序列化,并且文件中的数据尽可能的压缩以降低存储空间的消耗,目前也被Hive、Spark SQL、Presto
等查询引擎支持。2015年ORC项目被Apache项目基金会提升为Apache顶级项目。
ORC文件也是以二进制方式存储的,所以是不可以直接读取,ORC文件也是自解析的,它包含
许多的元数据,这些元数据都是同构ProtoBuffer进行序列化的。其中涉及到如下的概念:
ORC文件:保存在文件系统上的普通二进制文件,一个ORC文件中可以包含多个stripe,每一
个stripe包含多条记录,这些记录按照列进行独立存储,对应到Parquet中的row group的概念。
文件级元数据:包括文件的描述信息PostScript、文件meta信息(包括整个文件的统计信息)、
所有stripe的信息和文件schema信息。
stripe:一组行形成一个stripe,每次读取文件是以行组为单位的,一般为HDFS的块大小,保
存了每一列的索引和数据。
stripe元数据:保存stripe的位置、每一个列的在该stripe的统计信息以及所有的stream类型和
位置。
row group:索引的最小单位,一个stripe中包含多个row group,默认为10000个值组成。
stream:一个stream表示文件中一段有效的数据,包括索引和数据两类。索引stream保存每一
个row group的位置和统计信息,数据stream包括多种类型的数据,具体需要哪几种是由该列类型
和编码方式决定。
ORC文件中保存了三个层级的统计信息,分别为文件级别、stripe级别和row group级别的,
他们都可以用来根据Search ARGuments(谓词下推条件)判断是否可以跳过某些数据,在统计信
息中都包含成员数和是否有null值,并且对于不同类型的数据设置一些特定的统计信息。
⚫ 性能测试:
◼ 原始Text格式,未压缩 : 38.1 G
◼ ORC格式,默认压缩(ZLIB): 11.5 G
◼ Parquet格式,默认压缩(Snappy):14.8 G
◼ 测试对比:复杂数据Join关联测试
在这里插入图片描述
◼ ORC的优点
◼ 列式存储,存储效率非常高
◼ 可压缩,高效的列存取
◼ 查询效率较高,支持索引
◼ 支持矢量化查询
◼ ORC的缺点
◼ 加载时性能消耗较大
◼ 需要通过text文件转化生成
◼ 读取全量数据时性能较差
◼ ORC的应用
◼ 适用于Hive中大型的存储、查询
◼ ORC的使用
◼ 创建ORC数据表

create table tb_sogou_orc(
stime string,
userid string,
keyword string,
clickorder string,
url string
)
row format delimited fields terminated by ' '\t' '
stored as orc;

◼ 写入ORC数据表

insert into table tb_sogou_orc
select * from tb_sogou_source;

◼ 查询数据
在这里插入图片描述

2 数据压缩

2.1 压缩概述

Hive底层转换HQL运行MapReduce程序时,磁盘I/O操作、网络数据传输、shuffle和merge要
花大量的时间,尤其是数据规模很大和工作负载密集的情况下,鉴于磁盘I/O和网络带宽是Hadoop
的宝贵资源,数据压缩对于节省资源、最小化磁盘I/O和网络传输非常有帮助。如果磁盘I/O和网络
带宽影响了MapReduce作业性能,在任意MapReduce阶段启用压缩都可以改善端到端处理时间并
减少I/O和网络流量。
⚫ 压缩的优点
◼ 减小文件存储所占空间
◼ 加快文件传输效率,从而提高系统的处理速度
◼ 降低IO读写的次数
⚫ 压缩的缺点
◼ 使用数据时需要先对文件解压,加重CPU负荷,压缩算法越复杂,解压时间越长
⚫ Hadoop中各种压缩算法对比
在这里插入图片描述

2.2 Hive中压缩配置

Hive中的压缩就是使用了Hadoop中的压缩实现的,所以Hadoop中支持的压缩在Hive中都可
以直接使用。
Hadoop中支持的压缩算法:
在这里插入图片描述
要想在Hive中使用压缩,需要对MapReduce和Hive进行相应的配置
⚫ 临时配置
◼ 配置MapReduce开启输出压缩及配置压缩类型
–开启输出压缩
set mapreduce.output.fileoutputformat.compress= true;
–配置压缩类型为 Snappy
set
mapreduce.output.fileoutputformat.compress.codec=org.apache.hadoop.io.compres
s.SnappyCodec;
◼ 配置Hive开启中间结果压缩和输出压缩及配置压缩类型

-- 中间结果压缩
set hive.exec.compress.intermediate= true; ;
set
hive.intermediate.compression.codec=org.apache.hadoop.io.compress.Snap
pyCodec;
-- 输出结果压缩
set hive.exec.compress.output= true;

⚫ 永久配置
◼ 将以上MapReduce的配置写入mapred-site.xml中,重启Hadoop
◼ 将以上Hive的配置写入hive-site.xml中,重启Hive

2.3 Hive中压缩测试

⚫ 创建表,指定为textfile格式,并使用snappy压缩
create table tb_sogou_snappy
stored as textfile
as select * from tb_sogou_source;
⚫ 查看数据
在这里插入图片描述
⚫ 创建表,指定为orc格式,并使用snappy压缩
create table tb_sogou_orc_snappy
stored as orc tblproperties (“orc.compress”=“SNAPPY”)
as select * from tb_sogou_source;
⚫ 查看数据
在这里插入图片描述

3 存储优化

3.1 避免小文件生成

Hive的存储本质还是HDFS,HDFS是不利于小文件存储的,因为每个小文件会产生一条元数据
信息,并且不利用MapReduce的处理,MapReduce中每个小文件会启动一个MapTask计算处理,
导致资源的浪费,所以在使用Hive进行处理分析时,要尽量避免小文件的生成。
那么在使用Hive时,如何能避免小文件的生成呢?当我们使用多个Reduce进行聚合计算时,
我们并不清楚每个Reduce最终会生成的结果的数据大小,无法控制用几个Reduce来处理。Hive中
为我们提供了一个特殊的机制,可以自动的判断是否是小文件,如果是小文件可以自动将小文件进
行合并。
⚫ 配置
– 如果 hive 的程序,只有 maptask,将 MapTask 产生的所有小文件进行合并
set hive.merge.mapfiles= true;
– 如果 hive 的程序,有 Map 和 ReduceTask,将 ReduceTask 产生的所有小文件进行合

set hive.merge.mapredfiles= true;
– 每一个合并的文件的大小
set hive.merge.size.per.task=256000000;
– 平均每个文件的大小,如果小于这个值就会进行合并
set hive.merge.smallfiles.avgsize=16000000;

3.2 读取小文件

尽管我们通过配置避免了多个小文件的同时产生,但是我们总会遇到数据处理的中间结果是小
文件的情况,例如每个小时的分区数据中,大多数小时的数据都比较多,但是个别几个小时,如凌
晨的2点~6点等等,数据量比较小,下一步进行处理时就必须对多个小文件进行处理,那么这种场
景下怎么解决呢?
类似于MapReduce中的解决方案,Hive中也提供一种输入类CombineHiveInputFormat,用于
将小文件合并以后,再进行处理。
⚫ 配置
– 设置 Hive 中底层 MapReduce 读取数据的输入类:将所有文件合并为一个大文件作
为输入
set hive.input.format=org.apache.hadoop.hive.ql.io.CombineHiveInputFormat;

3.3 ORC文件索引

在使用ORC文件时,为了加快读取ORC文件中的数据内容,ORC提供了两种索引机制:Row
Group Index 和 Bloom Filter Index可以帮助提高查询ORC文件的性能,当用户写入数据时,可以
指定构建索引,当用户查询数据时,可以根据索引提前对数据进行过滤,避免不必要的数据扫描。
⚫ Row Group Index
一个ORC文件包含一个或多个stripes(groups of row data),每个stripe中包含了每个
column的min/max值的索引数据,当查询中有<,>,=的操作时,会根据min/max值,跳过扫描
不包含的stripes。而其中为每个stripe建立的包含min/max值的索引,就称为Row Group Index
行组索引,也叫min-max Index大小对比索引,或者Storage Index。
在建立ORC格式表时,指定表参数’orc.create.index’=’true’之后,便会建立Row Group
Index,需要注意的是,为了使Row Group Index有效利用,向表中加载数据时,必须对需要
使用索引的字段进行排序,否则,min/max会失去意义。另外,这种索引主要用于数值型字段
的范围查询过滤优化上。
在这里插入图片描述
◼ 开启索引配置
set hive.optimize.index.filter= true;
永久生效,请配置在hive-site.xml中
◼ 创建表,并指定构建索引
create table tb_sogou_orc_index
stored as orc tblproperties (“orc.create.index”=“true”)
as select * from tb_sogou_source
distribute by stime
sort by stime;
◼ 当进行范围或者等值查询(<,>,=)时就可以基于构建的索引进行查询
select count ( * ) from tb_sogou_orc_index where stime > ‘12:00:00’ and stime
< ‘18:00:00’;
⚫ Bloom Filter Index
建表时候,通过表参数”orc.bloom.filter.columns”=”columnName……”来指定为哪些字段
建立BloomFilter索引,这样,在生成数据的时候,会在每个stripe中,为该字段建立BloomFilter
的数据结构,当查询条件中包含对该字段的=号过滤时候,先从BloomFilter中获取以下是否包
含该值,如果不包含,则跳过该stripe。
◼ 创建表,并指定构建索引
create table tb_sogou_orc_bloom
stored as orc tblproperties
(“orc.create.index”=“true”,orc.bloom.filter.columns"=“stime,userid”)
as select * from tb_sogou_source
distribute by stime
sort by stime;
◼ stime的范围过滤可以走row group index,userid的过滤可以走bloom filter index
select
count(*)
from tb_sogou_orc_index
wh ere stime > ‘12:00:00’ and stime < ‘18:00:00’
and userid = ‘3933365481995287’ ;

3.4 ORC矢量化查询

Hive的默认查询执行引擎一次处理一行,而矢量化查询执行是一种Hive针对ORC文件操作的特
性,目的是按照每批1024行读取数据,并且一次性对整个记录整合(而不是对单条记录)应用操作,
提升了像过滤, 联合, 聚合等等操作的性能。
注意:要使用矢量化查询执行,就必须以ORC格式存储数据。
⚫ 配置
set hive.vectorized.execution.enabled = true;
set hive.vectorized.execution.reduce.enabled = true;

Guess you like

Origin blog.csdn.net/ZGL_cyy/article/details/121860985