一、Hive的数据压缩
(一) 数据压缩的优缺点
优点:
减少存储磁盘空间,降低单节点的磁盘IO。
减少网络传输带宽 ,因此可以加快数据在Hadoop集群流动的速度。
缺点:
需要花费额外的时间/CPU做压缩和解压缩计算。
(二)MR支持的压缩编码
Hadoop引入了编码/解码器
压缩格式 对应的编码/解码器
(三) 压缩配置参数
要在Hadoop中启用压缩,可以配置如下参数(mapred-site.xml文件中):
(四) 几种压缩方式的优缺点及应用场景
- Gzip
优点: 压缩率比较高,压缩/解压速度也比较快,hadoop本身支持。
缺点: 不支持分片。
应用场景:当每个文件压缩之后在1个block块大小内, 可以考虑用gzip压缩格式。 - Bzip2
优点: 支持分片,具有很高的压缩率,比gzip压缩率都高,Hadoop本身支持。
缺点: 压缩/解压速度慢,不支持Hadoop native库。
应用场景: 可以作为mapreduce作业的输出格式,输出之后的数据比较大,处理之后的数据需要压缩存档减少磁盘
空间并且以后数据用得比较少的情况。
- LZO
优点: 压缩/解压速度也比较快,合理的压缩率,支持分片,是Hadoop中最流行的压缩格式,支持Hadoop native库。 可以在linux系统下安装lzop命令,使用方便。
缺点: 压缩率比gzip要低一些,Hadoop本身不支持,需要安装,如果支持分片需要建立索引,还需要指定inputformat改为lzo格式。
应用场景:一个很大的文本文件,压缩之后还大于200M以上的可以考虑,而且单个文件越大,lzo优点越明显。 - Snappy
优点: 支持Hadoop native库,高速压缩速度和合理的压缩率。
缺点: 不支持分片,压缩率比gzip要低,Hadoop本身不支持,需要安装。
应用场景:当MapReduce作业的map输出的数据比较大的时候,作为map到reduce的中间数据的压缩格式。 - 总结
压缩比: bzip2 > gzip > lzo > snappy
压缩和解压缩速度,与压缩比成反比: snappy > lzo> gzip > bzip2
BZip2,LZO提供了块(BLOCK)级别的压缩,支持split切分;而snappy,gzip将文件中记录的边界信息掩盖掉了,因此不支持split切分。
(五) 开启Map输出阶段压缩
开启map输出阶段压缩可以减少job中map和Reduce task间数据传输量。具体配置如下:
1)开启hive中间传输数据压缩功能
hive (default)>set hive.exec.compress.intermediate=true;
2)开启mapreduce中map输出压缩功能
hive (default)>set mapreduce.map.output.compress=true;
3)设置mapreduce中map输出数据的压缩方式
hive (default)>set mapreduce.map.output.compress.codec= org.apache.hadoop.io.compress.SnappyCodec;
4)执行查询语句
select count(1) from score;
(六) 开启Reduce输出阶段压缩
当Hive将输出写入到表中时,输出内容同样可以进行压缩。属性 hive.exec.compress.output 控制着这个功能。
用户可能需要保持默认设置文件中的默认值false,这样默认的输出就是非压缩的纯文本文件了。
用户可以通过在查询语句或执行脚本中设置这个值为true,来开启输出结果压缩功能。
案例实操:
1)开启hive最终输出数据压缩功能
hive (default)>set hive.exec.compress.output=true;
2)开启mapreduce最终输出数据压缩
hive (default)>set mapreduce.output.fileoutputformat.compress=true;
3)设置mapreduce最终数据输出压缩方式
hive (default)> set mapreduce.output.fileoutputformat.compress.codec = org.apache.hadoop.io.compress.SnappyCodec;
4)设置mapreduce最终数据输出压缩为块压缩
hive(default)>set mapreduce.output.fileoutputformat.compress.type=BLOCK;
5)测试一下输出结果是否是压缩文件
insert overwrite local directory ‘/export/servers/snappy’ select * from score distribute by s_id sort by s_id desc;
二、Hive的数据存储格式
(一) Hive可概括为六种存储格式
TEXTFILE
SEQUENCEFILE
AVRO FILE
PARQUET
RCFILE
ORCFILE
在其中textfile为默认格式,如果在创建hive表不提及,会默认启动textfile格式,导入数据时会直接把数据文件拷贝到hdfs上不进行处理;与此同时,sequencefile,rcfile,orcfile自己不能直接从本地导入数据,需要将数据转为textfile格式,才能导入三种不同的格式。
(二) 简单介绍其特点
- TEXTFILE
理论
默认格式,数据不做压缩,磁盘开销大,数据解析开销大。
可结合Gzip、Bzip2使用(系统自动检查,执行查询时自动解压),但使用这种方式,hive不会对数据进行切分,从而无法对数据进行并行操作。
存储方式:行存储
实例测试
create table if not exists textfile_table
(
ueserid STRING,
movieid STRING,
rating STRING,
ts STRING
)
row format delimited fields terminated by ‘\t’
stored as textfile;
set hive.exec.compress.output=true;
set mapred.output.compress=true;
set mapred.output.compression.codec=org.apache.hadoop.io.compress.GzipCodec;
set io.compression.codecs=org.apache.hadoop.io.compress.GzipCodec;
insert overwrite table textfile_table select * from textfile_table;
2. SEQUENCEFILE
理论
二进制文件,以<key,value>的形式序列化到文件中;
SequenceFile是Hadoop API提供的一种二进制文件支持,其具有使用方便、可分割、可压缩的特点;
SequenceFile支持三种压缩选择:NONE,RECORD,BLOCK;
Record压缩率低,一般建议使用BLOCK压缩;
存储方式:行存储
实例测试
create table if not exists seqfile_table
(
ueserid STRING,
movieid STRING,
rating STRING,
ts STRING
)
row format delimited
fields terminated by ‘\t’
stored as sequencefile;
set hive.exec.compress.output=true;
set mapred.output.compress=true;
set mapred.output.compression.codec=org.apache.hadoop.io.compress.GzipCodec;
set io.compression.codecs=org.apache.hadoop.io.compress.GzipCodec;
SET mapred.output.compression.type=BLOCK;
insert overwrite table seqfile_table select * from textfile_table;
3. AVRO FILE
理论
Avro是一个数据序列化系统,设计用于支持大批量数据交换的应用。支持二进制序列化方式,可以便捷,快速地处理大量数据;动态语言友好,Avro提供的机制使动态语言可以方便地处理Avro数据。
存储方式:Avro依赖模式(Schema)来实现数据结构定义。可以把模式理解为Java的类,它定义每个实例的结构,可以包含哪些属性。可以根据类来产生任意多个实例对象
实例测试
– 方式一:高版本可以直接 STORED AS avro
– 高版本的hive,可以直接使用avro格式存储,而不需要手动指定avro的schema文件,hive自己会根据table的创建方式自行解析并将schema存储到文件的头部。
CREATE TABLE if not exists test_avro
(
id
STRING,
desc
STRING
)
ROW FORMAT DELIMITED FIELDS TERMINATED BY ‘,’
STORED AS avro;
– 方式二:低版本|高版本 hive
– 1)在创建表的时候,指定schema文件,表的属性为空。(Use avro.schema.url)
– avro.schema.url可以 url 。
– avro.schema.url也可以指向hdfs地址。
CREATE TABLE kst
PARTITIONED BY (ds string)
ROW FORMAT SERDE
‘org.apache.hadoop.hive.serde2.avro.AvroSerDe’
STORED AS INPUTFORMAT
‘org.apache.hadoop.hive.ql.io.avro.AvroContainerInputFormat’
OUTPUTFORMAT
‘org.apache.hadoop.hive.ql.io.avro.AvroContainerOutputFormat’
TBLPROPERTIES (‘avro.schema.url’=‘http://schema_provider/kst.avsc’);
/**
kst.avsc 内容
{
“namespace”: “com.linkedin.haivvreo”,
“name”: “test_serializer”,
“type”: “record”,
“fields”: [
{ “name”:“string1”, “type”:“string” },
{ “name”:“int1”, “type”:“int” },
{ “name”:“tinyint1”, “type”:“int” },
{ “name”:“smallint1”, “type”:“int” },
{ “name”:“bigint1”, “type”:“long” },
{ “name”:“boolean1”, “type”:“boolean” },
{ “name”:“float1”, “type”:“float” },
{ “name”:“double1”, “type”:“double” },
{ “name”:“list1”, “type”:{“type”:“array”, “items”:“string”} },
{ “name”:“map1”, “type”:{“type”:“map”, “values”:“int”} },
{ “name”:“struct1”, “type”:{“type”:“record”, “name”:“struct1_name”, “fields”: [
{ “name”:“sInt”, “type”:“int” }, { “name”:“sBoolean”, “type”:“boolean” }, { “name”:“sString”, “type”:“string” } ] } },
{ “name”:“union1”, “type”:[“float”, “boolean”, “string”] },
{ “name”:“enum1”, “type”:{“type”:“enum”, “name”:“enum1_values”, “symbols”:[“BLUE”,“RED”, “GREEN”]} },
{ “name”:“nullableint”, “type”:[“int”, “null”] },
{ “name”:“bytes1”, “type”:“bytes” },
{ “name”:“fixed1”, “type”:{“type”:“fixed”, “name”:“threebytes”, “size”:3} }
] }
*/
– 方式三:低版本|高版本 hive
– 2) schema直接写在table语句中
CREATE EXTERNAL TABLE tweets
COMMENT “A table backed by Avro data with the
Avro schema embedded in the CREATE TABLE statement”
ROW FORMAT SERDE ‘org.apache.hadoop.hive.serde2.avro.AvroSerDe’
STORED AS
INPUTFORMAT ‘org.apache.hadoop.hive.ql.io.avro.AvroContainerInputFormat’
OUTPUTFORMAT ‘org.apache.hadoop.hive.ql.io.avro.AvroContainerOutputFormat’
LOCATION ‘/user/wyp/examples/input/’
TBLPROPERTIES (
‘avro.schema.literal’=‘{
“type”: “record”,
“name”: “Tweet”,
“namespace”: “com.miguno.avro”,
“fields”: [
{ “name”:“username”, “type”:“string”},
{ “name”:“tweet”, “type”:“string”},
{ “name”:“timestamp”, “type”:“long”}
]
}’
);