Hive - 数据存储格式详解2(TextFile格式)
作者:hangge | 2024-10-06 09:52
二、TextFile 格式
1,基本介绍
(1)TextFile 是 Hive 的默认数据存储格式,基于行存储。
(2)TextFile 的主要特点是磁盘存储开销大,数据解析开销大。
- 磁盘存储开销大:因为存储的是原始文件内容,没有使用压缩,所以存储开销会比较大。
- 数据解析开销大:因为在反序列化读取数据的过程中,必须逐个字符判断是不是字段分隔符和行结束符,所以数据解析开销大。
(3)如果想要减少磁盘存储开销,也可以对 TextFile 格式的数据进行压缩,但是部分压缩格式在 Hive 中无法切割。
提示:数据的压缩格式其实是在 MapReduce 中提出的,因为 Hive 底层支持 MapReduce,所以 Hive 中也支持这些压缩格式。关于 MapReduce 压缩格式的详细介绍,可以参考我之前写的另一篇文章:
2,不带压缩的普通表
(1)首先需要生成一些测试数据,测试数据代码如下:
public class GenerateHiveData { public static void main(String[] args) throws Exception{ String fileName = "D:\\student.dat"; System.out.println("start: 开始生成文件->"+fileName); BufferedWriter bfw = new BufferedWriter(new FileWriter(fileName)); int num = 0; while(num<52000000){ bfw.write("1"+num+",hangge"+num+",nanjing"+num); bfw.newLine(); num ++; if(num%10000==0){ bfw.flush(); } } System.out.println("end: 文件已生成"); } }
- 代码执行完毕后会生成一个 2G 的数据文件:
- 文件里面内容如下:
create external table stu_textfile( id int, name string, city string ) row format delimited fields terminated by ',' lines terminated by '\n' location '/stu_textfile';
(3)然后把测试数据加载到这个表中:
load data local inpath '/root/student.dat' into table stu_textfile;
(4)最后确认通过表 stu_textfile 是否可以查到数据:
select * from stu_textfile limit 1;
3,使用 Defalte 压缩格式
(1)接下来我们基于 stu_textfile 这个普通数据表构建一个新的压缩数据表。
提示:这个压缩数据表的建表语句和普通表没有区别,唯一的区别就是在向表中添加数据的时候指定数据压缩格式。
create external table stu_textfile_deflate_compress( id int, name string, city string ) row format delimited fields terminated by ',' lines terminated by '\n' location '/stu_textfile_deflate_compress';
(2)Hive 中默认是没有开启压缩的,我们执行如下命令开启 Hive 输出数据压缩功能,并且设置使用 deflate 压缩格式:
set hive.exec.compress.output=true; set mapreduce.output.fileoutputformat.compress=true; set mapreduce.output.fileoutputformat.compress.codec=org.apache.hadoop.io.compress.DeflateCodec;
- 如果后期不确定使用的是哪种压缩格式,可以通过这条命令查看:
set mapreduce.output.fileoutputformat.compress.codec;
(3)接下来通过 insert into select 从普通表中查询数据,插入到压缩表中。
- 在这里我们设置 mapreduce.job.reduces=1,表示将结果数据写入到一个数据文件中,这也便于后面验证这个数据文件是否支持 Split。
注意:为了能够控制任务最终产生的数据文件个数,在这里通过 mapreduce.job.reduces 来控制,并且 SQL 语句中需要有可以产生 shuffle 的操作,如果是普通的 select 语句,最终是不会产生 Reduce 任务的,那么 mapreduce.job.reduces 这个参数就无法生效了。
set mapreduce.job.reduces=1; insert into stu_textfile_deflate_compress select id,name,city from stu_textfile group by id,name,city;
- 可以看到最终产生的数据文件大小为 353M:
(5)接下来写一个 sql 查询压缩表中的数据,确认一下是否会生成多个 Map 任务。
select id,count(*) from stu_textfile_deflate_compress group by id;
- 在这里发现这个 SQL 最终只生成了 1 个 Map 任务,也就意味着这个 353M 的文件是有一个 Map 任务负责计算,这也符合 deflate 压缩格式的特点。
(6)最后,这个压缩表中的数据查看后最好删除一下,这样可以释放 HDFS 存储空间。
hdfs dfs -rm -r -skipTrash /stu_textfile_deflate_compress
4,使用 Bzip2 压缩格式
(1)接下来我们基于 stu_textfile 这个普通数据表构建一个新的压缩数据表。
提示:这个压缩数据表的建表语句和普通表没有区别,唯一的区别就是在向表中添加数据的时候指定数据压缩格式。
create external table stu_textfile_bzip2_compress( id int, name string, city string ) row format delimited fields terminated by ',' lines terminated by '\n' location '/stu_textfile_bzip2_compress';
(2)Hive 中默认是没有开启压缩的,我们执行如下命令开启 Hive 输出数据压缩功能,并且设置使用 Bzip2 压缩格式:
set hive.exec.compress.output=true; set mapreduce.output.fileoutputformat.compress=true; set mapreduce.output.fileoutputformat.compress.codec=org.apache.hadoop.io.compress.BZip2Codec;
- 如果后期不确定使用的是哪种压缩格式,可以通过这条命令查看:
set mapreduce.output.fileoutputformat.compress.codec;
(3)接下来通过 insert into select 从普通表中查询数据,插入到压缩表中。
- 在这里我们设置 mapreduce.job.reduces=1,表示将结果数据写入到一个数据文件中,这也便于后面验证这个数据文件是否支持 Split。
注意:为了能够控制任务最终产生的数据文件个数,在这里通过 mapreduce.job.reduces 来控制,并且 SQL 语句中需要有可以产生 shuffle 的操作,如果是普通的 select 语句,最终是不会产生 Reduce 任务的,那么 mapreduce.job.reduces 这个参数就无法生效了。
set mapreduce.job.reduces=1; insert into stu_textfile_bzip2_compress select id,name,city from stu_textfile group by id,name,city;
- 可以看到最终产生的数据文件大小为 157M:
(5)接下来写一个 sql 查询压缩表中的数据,确认一下是否会生成多个 Map 任务。
select id,count(*) from stu_textfile_bzip2_compress group by id;
- 结果发现只产生了 1 个 Map 任务,正常情况下这份数据会被切分成 2 个 Split,产生 2 个 Map 任务的。这是因为 Hive 中默认的 Split 大小是 244M,这个结果文件小于 244M,所以 Hive 最终只切分了 1 个 Split,也就只产生了 1 个 Map 任务。
- Hive 在读取数据的时候目前使用的是 CombineHiveInputFormat,其在切分 Split 的时候会参考 mapred.max.split.size 参数的值。我们可以将 mapred.max.split.size 参数的值改为 128M 来验证一下。
set mapred.max.split.size=134217728;
- 再次查询可以发现产生了 2 个 Map 任务,最终可以确认,在 Hive 中 Bzip2 压缩文件也是支持切分的。
(6)最后,这个压缩表中的数据查看后最好删除一下,这样可以释放 HDFS 存储空间。
hdfs dfs -rm -r -skipTrash /stu_textfile_bzip2_compress
全部评论(0)