Hive和Spark当中对小文件的处理
Hive当中对小文件的处理
数仓面试高频考点:
【在Hive中如何解析小文件过多问题,指定的是:处理表中数据时,有很多小文件】
- 查看表中【文件个数、数据量和数据大小】
如何查看?
命令:
desc formatted db_hive.emp ;
| Table Parameters: | NULL | NULL |
| | bucketing_version | 2 |
| | numFiles | 1 |
| | numRows | 0 |
| | rawDataSize | 0 |
| | totalSize | 656 |
| | transient_lastDdlTime | 1631525001 |
如果没有显示表的统计信息,执行如下命令,再次查看表信息
ANALYZE TABLE db_hive.emp COMPUTE STATISTICS;
| Table Parameters: | NULL | NULL |
| | COLUMN_STATS_ACCURATE | {"BASIC_STATS":"true"} |
| | bucketing_version | 2 |
| | numFiles | 1 |
| | numRows | 14 |
| | rawDataSize | 643 |
| | totalSize | 656 |
| | transient_lastDdlTime | 1655113125 |
| | NULL | NULL |
-
分析:Hive表数据,为什么有小文件?
第1步、向hive表加载数据方式
a. 直接向表插入数据:insert
insert into table t1 values(1, "zhangsan", 99), (2, "lisi", 88)
每次执行,产生一个文件,如果执行多次,产生多个文件
此种方式几乎在生产环境不使用
b. 通过load方式加载数据
load data local inpath '/export/data/xx.data' overwrite into table t1
load data local inpath '/export/data/20220612' overwrite into table t1
此种方式不会,除非导入文件就是小文件c. 查询方式加载数据
insert into table t1 select * from t2 ;
【此种方式生产环境经常使用,肯定会产生小文件,最容易产生小文件】insert导入数据时,启动运行MR任务,有多少个Reduce就有多少个输出文件
-
小文件过多,有什么影响?
a. 对于HDFS文件系统来说,每个文件存储都需要在NameNode中存储元数据
小文件过多,使用更多内存存储
b. 对Hive中查询分析来说,每个小文件就是block存储,对应1个MapTask
启动太多MapTask进程处理数据,浪费资源和时间,性能直线下降 -
如何解决小文件呢?
a. 合并小文件:自动合并
【当Hive表中数据存储格式为:ORC或RCFile时,可以设置属性】
https://cwiki.apache.org/confluence/display/Hive/LanguageManual+DDL#LanguageManualDDL-AlterTable/PartitionConcatenate
第1点、非分区表
ALTER TABLE t1 CONCATENATE;
第2点、分区表
ALTER TABLE t2 PARTITION (day_str = '2022-06-12') CONCATENATE;b. 调用MapReduce处理数据时,相关参数
执行map前小文件合并
set hive.input.format=org.apache.hadoop.hive.ql.io.CombineHiveInputFormat;
设置合并文件大小
set hive.merge.size.per.task = 25610001000;
Spark当中对小文件的处理
第一种,将小文件合并成一个大文件
第二种,使用SparkContext中提供:wholeTextFiles
方法,专门读取小文件数据。
将每个文件作为一条KV存储在RDD中,K:文件名的绝对路径,V:文件的内容
用于解决小文件的问题,可以将多个小文件变成多个KV,自由指定分区个数