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 指定压缩 hive开启压缩_hive


当我们选择使用行式存储,查询所有字段的时候,查询效率最高,如:

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;