Hive压缩、存储与优化

1、Hive压缩

  • 概述:Hive的压缩是MR的压缩,分为Map端结果文件压缩和Reduce端结果文件压缩
  • 压缩性能比较
压缩算法 原始文件大小 压缩文件大小 压缩速度 解压速度
gzip 8.3GB 1.8GB 17.5MB/s 58MB/s
bzip2 8.3GB 1.1GB 2.4MB/s 9.5MB/s
LZO 8.3GB 2.9GB 49.3MB/s 74.6MB/s
Snappy 8.3GB 3G 250MB/S 500 MB/s

按照Hive对数据的分层,我们可以在对应层使用这样的压缩方式:

层级 压缩方式 原因
ODS层 zlib、gz、bz2 省空间
DW层 snappy 速度快
DA层 snappy 速度快
  • 相关参数设置
-- 开启Map端压缩
set hive.exec.compress.intermediate=true;
set mapreduce.map.output.compress=true;
set mapreduce.map.output.compress.codec= org.apache.hadoop.io.compress.SnappyCodec;

-- 开启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;

2、Hive存储格式

  • hive的存储格式分为行式存储和列式存储
  • hive的默认存储方式是行式存储中的TextFile,除此之外,还有SequenceFile
  • 列式存储也有两个:ORC和PARQUET

以下是行式存储和列式存储的示意图
Hive压缩、存储与优化_第1张图片
当我们选择使用行式存储,查询所有字段的时候,查询效率最高,如:

SELECT * FROM TABLE_NAME [WHERE  CONDITION]

但是,如果查询具体某几个字段时,查询效率就比较低,但对于列式存储来说,效率却能得到很大提升。一般项目中,我们使用的是列式存储,一般使用的是ORC存储

  • 建表时指定存储格式

这过程中,使用ORC列式存储方式的数据会进行压缩,使数据的摆放方式更加合理。
orc内部默认采用的压缩算法是zlib

-- 建表(默认)
create table test_text (
	id int,
	name string
)
row format delimited fields terminated by '\t';
-- 加载数据到test_text 
load data inpath '/hive/text.log' into test_text;
-- 建表(orc)
create table test_orc (
	id int,
	name string
)
row format delimited fields terminated by '\t'
stored as orc;
-- 加载数据,查询并插入(执行MapReduce)
insert into test_orc select * from test_text;
  • 建表时指定存储格式的压缩算法

上面说到ORC的默认压缩算法为zlib,我们也可以通过设置去指定其压缩算法

create table test_orc_snappy(
id int,
name string
)
ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t'
STORED AS orc tblproperties ("orc.compress"="SNAPPY");

所以,结合压缩算法,我们对hive的分层中,可以通过存储格式和压缩方式进行结合,达到我们对每个分层的优化效果

层级 压缩方式 存储格式 原因
ODS层 zlib、gz、bz2 ORC 省空间
DW层 snappy ORC 速度快
DA层 snappy ORC 速度快

3、Hive优化

  • 本地调优
    在本地模式时,在数据量小的情况下,可以通过设置以下方法,达到优化查询的目的
set hive.stats.column.autogather=false;
set hive.exec.mode.local.auto=true;

3.1、空key问题

  • 谓词下推

在做join操作的时候,如果本身数据存在null值,那么联表时会造成很多非必要的链表操作,此时我们可以在联表前做空key的过滤操作

select * from  A a  where 过滤条件
select * from  B a  where 过滤条件

select * from (select * from  A a  where 过滤条件) a  left  join  (select * from  B b 过滤条件) b  on 连接条件
  • 加盐操作

针对null值的待连接的表数据,有时候它本身的存在是有意义的,这时候不应该被过滤掉,可以考虑加盐操作,加盐还有个好处,就是防止数据在reduce端造成倾斜的情况

SELECT a.*
FROM Table1 a
LEFT JOIN Table2 b ON CASE WHEN a.id IS NULL THEN concat('table1', rand()) ELSE a.id END = b.id;

3.2、去重

  • distinct: 注意,在Hive中distinct必须只有一个reduce才能完成整体的去重,效率极低,千万不要用
  • group by
  • row_number() over():生产环境使用
select distinct * from;
select sid,sname,sbirth,ssex from  student2 group by sid,sname,sbirth,ssex; 
with t as (
 select
    *,
    row_number() over (partition by sid ) rk
 from student2
)
select * from t where rk = 1;

你可能感兴趣的:(博学谷学习记录,hive,hadoop,大数据)