本文已参与「新人创作礼」活动,一起开启掘金创作之路。
Hadoop压缩数据流程
hadoop中有三个阶段可以用到压缩,分别是Map,Shuffle和Reduce,其中Map阶段首先对输入的数据进行压缩,然后在Map的job中进行解压并对数据进行业务处理,将结果写入磁盘的时候进行数据的压缩,Shuffle的过程中将磁盘中压缩的文件内容读取出来,然后传递给Reduce,Reduce中对数据再进行解压并做业务处理,整个过程都计算完毕后再用压缩对输出进行压缩。其数据流程可以用下面的流程表示:
压缩的输入文件->(解压数据)->Maps->压缩输出->Spill to Disk(Shuffle)->解压输入->Reduces->压缩输出->压缩的输出文件
压缩算法比较
Linux操作系统中常见的压缩格式是bzip2、gzip、lzo、snappy这四种,这四种压缩方法的比较如下:
-
压缩比:bizp2>gzip>lzo(snappy) bzip2最节省空间
-
解压速度:lzo(snappy)>gzip>bzip2 lzo解压速度是最快的
解压速度消耗CPU资源,压缩比消耗磁盘空间,这两者要权衡一下,如果压缩比太大,那么解压速度就慢,耗费CPU就多。gzip是以.gz扩展名结尾的文件使用的压缩算法,一般开源软件的压缩包多采用这种格式。snappy是google开源出来的压缩算法,它旨在提供高速压缩速度和合理的压缩率,所以现在实际应用中多使用snappy压缩算法。之前安装的CDH集群默认使用的就是snappy压缩算法。
查看集群的支持的压缩算法
set io.compression.codecs;
压缩配置
Map输出压缩
开启MR中间结果map输出阶段压缩可以减少job中map和Reduce task间数据传输量。
set hive.exec.compress.intermediate=true;--开启hive中间传输数据压缩功能
set mapred.map.output.compression.codec= org.apache.hadoop.io.compress.SnappyCodec
开启MR最终输出Reduce输出压缩
set hive.exec.compress.output=true; --开启hive最终输出数据压缩功能
set mapred.output.compression.codec=org.apache.hadoop.io.compress.SnappyCodec;
set mapred.output.compression.type=BLOCK;--设置mapreduce最终数据输出压缩为块压缩,只有SEQUENCEFILE格式需要设置
hive压缩测试
数据仓库的特点:一次写入、多次读取,因此,整体来看,ORCFile相比其他格式具有较明显的优势。
- TextFile 默认格式,加载速度最快,可以采用Gzip、bzip2等进行压缩,压缩后的文件无法split,即并行处理
- SequenceFile 压缩率最低,查询速度一般,三种压缩格式NONE,RECORD,BLOCK
- RCfile 压缩率最高,查询速度最快,数据加载最慢。
通过参考大量案例,综合考虑hive执行速度与文件压缩比,另外textfile在数据中转数据加载时会经常用到, 因此选用textfile和orc存储格式使用snappy压缩格式进行比较测试。
生成数据表
生成测试数据脚本
#!/bin/bash env
touch data.txt
for((i=1;i<= 20000000;i++))
do
id=${i}
name="name"${i}
rand=""
second=""
datetime=""
line=${id}","${name}","${rand}","${second}","${datetime}
#echo ${line}
echo ${line} >> data.txt
done
创建数据源表
drop table db02.test1;
CREATE TABLE db02.test1(
id INT,
name STRING,
rand STRING,
second BIGINT,
datetime STRING)
ROW FORMAT DELIMITED
FIELDS TERMINATED BY ',' STORED AS TEXTFILE;
导入数据
--本地操作,需要数据文件在hiveserver所在服务服务器对应的目录
LOAD DATA LOCAL INPATH "/tmp/data/data.txt" OVERWRITE INTO TABLE db02.test1;
-- 需要数据文件在hdfs文件系统
LOAD DATA INPATH "/tmp/data/data.txt" OVERWRITE INTO TABLE db02.test1;
生成最终的【textfile格式 无压缩】的测试数据
INSERT OVERWRITE TABLE db02.test1
SELECT id,name,substr(cast(rand() as string),3) as rand,unix_timestamp() as second,current_timestamp() as datetime from db02.test1;
结果:
[root@bdpapp01 test]# hdfs dfs -du -s -h -v /warehouse/tablespace/managed/hive/db02.db/test1
SIZE DISK_SPACE_CONSUMED_WITH_ALL_REPLICAS FULL_PATH_NAME
1.3 G 4.0 G /warehouse/tablespace/managed/hive/db02.db/test1
orc SNAPPY压缩
drop table db02.test2;
CREATE TABLE IF NOT EXISTS db02.test2(
id INT,
name STRING,
rand STRING,
second BIGINT,
datetime STRING)
ROW FORMAT DELIMITED
FIELDS TERMINATED BY '\t'
NULL DEFINED AS ''
STORED AS ORC
TBLPROPERTIES('orc.compress' = 'SNAPPY');
--tez合并输出小文件
set hive.merge.tezfiles=true; -- Notifying that merge step is required
set hive.merge.size.per.task = 256000000;--合并后每个文件的大小
set hive.merge.smallfiles.avgsize=256000000;--当输出文件的平均大小小于256000000时,启动一个独立的MR任务进行文件合并,触发小文件合并的阀值
set hive.merge.orcfile.stripe.level=false; --当这个参数设置为true,orc文件进行stripe Level级别的合并,当设置为false,orc文件进行文件级别的合并。
set hive.merge.rcfile.block.level=false;--当这个参数设置为true,rcfile文件进行block Level级别的合并,当设置为false,rcfile文件进行文件级别的合并。
INSERT OVERWRITE TABLE db02.test2
SELECT
id,
name,
rand,
second,
datetime
FROM db02.test1;
结果:
[root@bdpapp01 test]# hdfs dfs -du -s -h -v /warehouse/tablespace/managed/hive/db02.db/test3
SIZE DISK_SPACE_CONSUMED_WITH_ALL_REPLICAS FULL_PATH_NAME
350.9 M 1.0 G /warehouse/tablespace/managed/hive/db02.db/test3
orc 在建表时不使用压缩格式
drop table db02.test3;
CREATE TABLE IF NOT EXISTS db02.test3(
id INT,
name STRING,
rand STRING,
second BIGINT,
datetime STRING)
ROW FORMAT DELIMITED
FIELDS TERMINATED BY '\t'
NULL DEFINED AS ''
STORED AS ORC
TBLPROPERTIES('orc.compress' = 'NONE');
INSERT OVERWRITE TABLE db02.test3
SELECT
id,
name,
rand,
second,
datetime
FROM db02.test1;
结果:
[root@bdpapp01 test]# hdfs dfs -du -s -h -v /warehouse/tablespace/managed/hive/db02.db/test3
SIZE DISK_SPACE_CONSUMED_WITH_ALL_REPLICAS FULL_PATH_NAME
547.9 M 1.6 G /warehouse/tablespace/managed/hive/db02.db/test3
textfile SNAPPY压缩
drop table db02.test4;
CREATE TABLE IF NOT EXISTS db02.test4(
id INT,
name STRING,
rand STRING,
second BIGINT,
datetime STRING)
ROW FORMAT DELIMITED
FIELDS TERMINATED BY '\t'
NULL DEFINED AS ''
STORED AS textfile;
set hive.exec.compress.output=true;
set mapred.output.compression.codec=org.apache.hadoop.io.compress.SnappyCodec;
INSERT OVERWRITE TABLE db02.test4
SELECT
id,
name,
rand,
second,
datetime
FROM db02.test1;
结果:
[root@bdpapp01 test]# hdfs dfs -du -s -h -v /warehouse/tablespace/managed/hive/db02.db/test4
SIZE DISK_SPACE_CONSUMED_WITH_ALL_REPLICAS FULL_PATH_NAME
455.4 M 1.3 G /warehouse/tablespace/managed/hive/db02.db/test4
测试结果分析:
- textfile 不压缩
[root@bdpapp01 test]# hdfs dfs -du -s -h -v /warehouse/tablespace/managed/hive/db02.db/test1
SIZE DISK_SPACE_CONSUMED_WITH_ALL_REPLICAS FULL_PATH_NAME
1.3 G 4.0 G /warehouse/tablespace/managed/hive/db02.db/test1
- textfile SNAPPY压缩
[root@bdpapp01 test]# hdfs dfs -du -s -h -v /warehouse/tablespace/managed/hive/db02.db/test4
SIZE DISK_SPACE_CONSUMED_WITH_ALL_REPLICAS FULL_PATH_NAME
455.4 M 1.3 G /warehouse/tablespace/managed/hive/db02.db/test4
- orc 不压缩
[root@bdpapp01 test]# hdfs dfs -du -s -h -v /warehouse/tablespace/managed/hive/db02.db/test3
SIZE DISK_SPACE_CONSUMED_WITH_ALL_REPLICAS FULL_PATH_NAME
547.9 M 1.6 G /warehouse/tablespace/managed/hive/db02.db/test3
- orc SNAPPY压缩
[root@bdpapp01 test]# hdfs dfs -du -s -h -v /warehouse/tablespace/managed/hive/db02.db/test2
SIZE DISK_SPACE_CONSUMED_WITH_ALL_REPLICAS FULL_PATH_NAME
350.9 M 1.0 G /warehouse/tablespace/managed/hive/db02.db/test2
通过比较分析,采用orc存储指定snappy压缩格式,无论在hive的执行效率还是压缩率上,表现都是最好的。
HiveQL语句指定ORC文件格式配置
| 配置 | 默认值 | 备注 |
|---|---|---|
| orc.compress | ZLIB | 高级压缩(one of NONE, ZLIB, SNAPPY) |
| orc.compress.size | 262,144 | 每个压缩块中的字节数 |
| orc.stripe.size | 67,108,864 | 每条stripe中的字节数 |
| orc.row.index.stride | 10,000 | 索引条目之间的行数(必须是>= 1000) |
| orc.create.index | true | 是否创建行索引 |
| orc.bloom.filter.columns | "" | 逗号分隔的列名列表,应该为其创建bloom过滤器 |
| orc.bloom.filter.fpp | 0.05 | bloom过滤器的误报概率(必须是>0.0和<1.0) |
案例:
CREATE TABLE tmp.orcTest stored AS ORC
TBLPROPERTIES
('orc.compress'='SNAPPY',
'orc.create.index'='true',
'orc.bloom.filter.fpp'='0.05',
'orc.stripe.size'='10485760',
'orc.row.index.stride'='10000')
AS
SELECT
*
FROM tmp.orcTextFile
DISTRIBUTE BY userid sort BY userid;
说明: orc存储文件默认采用ZLIB压缩。ZLIB压缩率比snappy的高,但是ZLIB解压缩速率很低。