(14)Hive调优——合并小文件

目录

一、小文件产生的原因

二、小文件的危害

三、小文件的解决方案

3.1 小文件的预防

3.1.1 减少Map数量

 3.1.2 减少Reduce的数量

3.2 已存在的小文件合并

3.2.1 方式一:insert overwrite (推荐)

 3.2.2 方式二:concatenate

 3.2.3 方式三:使用hive的archive归档

3.2.4 方式四:hadoop getmerge

一、小文件产生的原因

  • 数据源本身就包含大量的小文件,例如api,kafka消息管道等。
  • 动态分区插入数据的时候,会产生大量的小文件,从而导致map数量剧增;;
  • reduce 数量越多,小文件也越多,小文件数量=ReduceTask数量*分区数;
  • hive中的小文件是向 hive 表中导入数据时产生;

向 hive 中导入数据的几种方式:

(1)直接向表中插入数据

insert into table t_order2 values (1,'zhangsan',88),(2,'lisi',61);

     这种方式每次插入时都会产生一个小文件,多次插入少量数据就会出现多个小文件,故这种方式生产环境基本不使用;

(2)通过load方式加载数据

-- 导入文件
load data local inpath "/opt/module/hive_data/t_order.txt" overwrite into table t_order;
-- 导入文件夹
load data local inpath "/opt/module/hive_data/t_order" overwrite into table t_order;

     使用 load方式可以导入文件或文件夹,当导入一个文件时,hive表就有一个文件,当导入文件夹时,hive表的文件数量为文件夹下所有文件的数量;

(3)通过查询方式加载数据

insert overwrite t_order  select oid,uid from t_order2

   这种方式是生产环境中经常用的,也是最容易产生小文件的方式。insert 导入数据时会启动MR任务,MR-reduce的个数与输出文件个数一致。

    因此,hdfs的文件数量=  reduceTask数量* 分区数,有些fetch本地抓取任务(例如:简单的 select * from tableA)仅有map阶段,那此时文件个数 = mapTask数量*分区数

二、小文件的危害

        小文件通常是指文件大小要比HDFS块大小(一般是128M)还要小很多的文件。

  • NameNode在内存中维护整个文件系统的元数据镜像、其中每个HDFS文件元数据信息(位置、大小、分块等)对象约占150字节,如果小文件过多会占用大量内存,会直接影响NameNode性能。相对的,HDFS读写小文件也会更加耗时,因为每次都需要从NameNode获取元信息,并与对应的DataNode建立pipeline连接。

  • 从 Hive 角度看,一个小文件会开启一个 MapTask,一个 MapTask开一个 JVM 去执行,这些任务的启动及初始化,会浪费大量的资源,严重影响性能。

三、小文件的解决方案

   小文件的解决思路主要有两个方向:1.小文件的预防;2.已存在的小文件合并

3.1 小文件的预防

     通过调整参数进行合并,在 hive 中执行 insert overwrite  tableA select xx  from tableB 之前设置如下合并参数,即可自动合并小文件。

3.1.1 减少Map数量

         在Map前进行输入合并,从而减少mapper任务的数量。

  • 设置map输入时的合并参数:
#Map前进行小文件合并
#CombineHiveInputFormat底层是 Hadoop的CombineFileInputFormat方法,该方法是在mapper中将多个文件合成一个split切片作为输入
set hive.input.format=org.apache.hadoop.hive.ql.io.CombineHiveInputFormat; -- 默认开启#每个Map最大的输入数据量(这个值决定了合并后文件的数量,会影响mapper数量)
set mapred.max.split.size=256*1000*100;   -- 默认是256M#一个节点上split的至少的大小(这个值决定了多个DataNode上的文件是否需要合并)
set mapred.min.split.size.per.node=100*100*100;  -- 100M
#一个交换机下split的至少的大小(这个值决定了多个交换机上的文件是否需要合并)
set mapred.min.split.size.per.rack=100*100*100; -- 100M
  • 设置map端输出时和reduce端输出时的合并参数:
#设置map端输出进行合并,默认为true
set hive.merge.mapfiles = true;
#设置reduce端输出进行合并,默认为false
set hive.merge.mapredfiles = true;
#设置合并文件的大小
set hive.merge.size.per.task = 256*1000*1000;   -- 256M
#当输出文件的平均大小小于该值时,启动一个独立的MapReduce任务进行文件merge
set hive.merge.smallfiles.avgsize=16000000;   -- 16M
  • 启用压缩(小文件合并后,也可以选择启用压缩)
# hive的查询结果输出是否进行压缩
set hive.exec.compress.output=true;
# MapReduce Job的结果输出是否使用压缩
set mapreduce.output.fileoutputformat.compress=true;
#设置压缩方式是snappy
set parquet.compression = snappy;

 3.1.2 减少Reduce的数量

#reduce的个数决定了输出的文件的个数,所以可以调整reduce的个数控制hive表的文件数量,
#通过设置reduce的数量,利用distribute by使得数据均衡的进入每个reduce。
#设置reduce的数量有两种方式,第一种是直接设置reduce个数
set mapreduce.job.reduces=10;#第二种是设置每个reduceTask的大小,Hive会根据数据总大小猜测确定一个reduce个数
set hive.exec.reducers.bytes.per.reducer=512*1000*1000; -- 默认是1G,这里为设置为5G#执行以下语句,将数据均衡的分配到reduce中
set mapreduce.job.reduces=10;insert overwrite table A partition(dt)
select * from B
distribute by  cast(rand()*10 as int);解释:如设置reduce数量为10,则使用cast(rand()*10 as int),生成0-10之间的随机整数,根据【随机整数 % 10】计算分区编号,这样数据就会均衡的分发到各reduce中,防止出现有的文件过大或过小

3.2 已存在的小文件合并

      对集群上已存在的小文件进行定时或实时的合并操作,定时操作可在访问低峰期操作,如凌晨2点,合并操作主要有以下几种方式:

3.2.1 方式一:insert overwrite (推荐)

执行流程总体如下:

(1)创建备份表(创建备份表时需和原表的表结构一致)

create table test.table_hive_back like test.table_hive ;

(2)设置合并文件相关参数,并使用insert overwrite 语句读取原表,再插入备份表

  • 设置合并文件相关参数

       使用 hive的merger合并参数,在正式 insert overwrite 之前做一个合并,合并的时候注意设置好压缩,不然文件会比较大。

  • 合并文件至备份表中,执行前保证没有数据写入原表
#如果有多级分区,将分区名放到partition中
insert overwrite table test.table_hive_back partition(batch_date) 
select * from test.table_hive;

 psinsert overwrite table test.table_hive_back 备份表的时候,可以使用distribute by 命令设置合并后的batch_date分区下的文件数据量

insert overwrite table 目标表 [partition(hour=...)] select * from 目标表 
distribute by cast( rand() * 具体最后落地生成多少个文件数 as int);
  • insert overwrite会重写数据,先进行删除后插入(不用担心如果overwrite失败,数据没了,这里面是有事务保障的);

  • distribute by分区控制数据从map端发往到哪个reduceTask中,distribute by的分区规则:分区字段的hashcode值对reduce 个数取模后, 余数相同的数据会分发到同一个reduceTask中。

  • rand()函数:生成0-1的随机小数,控制最终输出多少个文件。

# 使用distribute by rand()将数据随机分配给reduce,这样可以使得每个reduce处理的数据大体一致。 避免出现有的文件特别大, 有的文件特别小,例如:控制dt分区目录下生成100个文件,那么hsql如下:
insert overwrite table A partition(dt)select * from B
distribute by cast(rand()*100 as int);#cast(rand()*100 as int) 可以生成0-100的随机整数

     如果合并之后的文件竟然还变大了,可能是 select from的原数据是被压缩的,但是insert overwrite目标表的时候,没有设置输出文件压缩功能,解决方案:

# hive的查询结果输出是否进行压缩
set hive.exec.compress.output=true;
# MapReduce Job的结果输出是否使用压缩
set mapreduce.output.fileoutputformat.compress=true;
#设置压缩方式是snappy
set parquet.compression = snappy;

(3)确认表数据一致后,将原表修改名称为临时表tmp,将备份表修改名称为原表

  • 先查看原表和备份表数据量,确保表数据一致
#查看原表和备份表数据量
set hive.compute.query.using.stats=false ;
set hive.fetch.task.conversion=none;
SELECT count(*) FROM test.table_hive;
SELECT count(*) FROM test.table_hive_back ;
  • 将原表修改名称为临时表tmp,将备份表修改名称为原表
alter table test.table_hive rename to test.table_hive_tmp;
alter table test.table_hive_back rename to test.table_hive ;

(4)查看合并后的分区数和小文件数量

    正常情况下:hdfs文件系统上的table_hive表的分区数量没有改变,但是每个分区的几个小文件已经合并为一个文件。

#统计合并后的分区数
[atguigu@bigdata102 ~]$ hdfs dfs -ls /user/hive/warehouse/test/table_hive
#统计合并后的分区数下的文件数
[atguigu@bigdata102 ~]$ hdfs dfs -ls /user/hive/warehouse/test/table_hive/batch_date=20210608

  例如:

(5)观察一段时间后再删除临时表

drop  table test.table_hive_tmp ;

     ps:注意修改hive表名的时候,对应表的存储路径会发生变化,如果有新的任务上传数据到具体路径,需要注意可能需要修改。

 3.2.2 方式二:concatenate

      对于orc文件,可以使用hive自带的 concatenate 命令,自动合并小文件

#对于非分区表
alter table test concatenate;#对于分区表
alter table test [partition(...)] concatenate
#例如:alter table test partition(dt='2021-05-07',hr='12') concatenate;

注意: 

  • concatenate 命令只支持 rcfile和 orc文件类型。 
  • concatenate命令合并小文件时不能指定合并后的文件数量,但可以多次执行该命令。 
  • 当多次使用concatenate后文件数量不变化,这个跟参数 mapreduce.input.fileinputformat.split.minsize=256mb 的设置有关,可设定每个文件的最小size。

 3.2.3 方式三:使用hive的archive归档

    每日定时脚本,对于已经产生小文件的hive表使用har归档,然后已归档的分区不能insert overwrite ,必须先unarchive

#用来控制归档是否可用
set hive.archive.enabled=true;#通知Hive在创建归档时是否可以设置父目录
set hive.archive.har.parentdir.settable=true;#控制需要归档文件的大小
set har.partfile.size=256000000;#对表的某个分区进行归档
alter table test_rownumber2 archive partition(dt='20230324');#对已归档的分区恢复为原文件
alter table test_rownumber2 unarchive partition(dt='20230324');

3.2.4 方式四:hadoop getmerge

  对于txt格式的文件可以使用hadoop getmerge命令来合并小文件。使用 getmerge 命令先合并数据到本地,再通过put命令回传数据到hdfs。

  • 将hdfs上分区为pdate=20220815,文件路径为  /user/hive/warehouse/xxxx.db/xxxx/pdate=20220815/* 下载到linux 本地进行合并文件,本地路径为:/home/hadoop/pdate/20220815

         hadoop fs -getmerge  /user/hive/warehouse/xxxx.db/xxxx/pdate=20220815/*  /home/hadoop/pdate/20220815;

  •  将hdfs源分区数据删除

        hadoop fs -rm  /user/hive/warehouse/xxxx.db/xxxx/pdate=20220815/*

  • 在hdfs上新建分区

      hadoop fs -mkdir -p /user/hive/warehouse/xxxx.db/xxxx/pdate=20220815

  • 将本地合并后的文件回传到hdfs上

         hadoop fs -put  /home/hadoop/pdate/20220815  /user/hive/warehouse/xxxx.db/xxxx/pdate=20220815/*

参考文章:

HIVE中小文件问题_hive小文件产生的原因-CSDN博客

Hive教程(09)- 彻底解决小文件的问题-阿里云开发者社区

0704-5.16.2-如何使用Hive合并小文件-腾讯云开发者社区-腾讯云

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/259483.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

svg之全局组件,配合雪碧图解决vue2的svg优化问题

这里是vue2中的svg的完整解决方案的另一篇。 <template><svg :class"svgClass"><use :xlink:href"#${name}"></use></svg> </template><script>export default {name: icon,props: {name: {type: String,requi…

双向bfs P1032 字串变换

传送门https://www.luogu.com.cn/problem/P1032 找一个最短方案&#xff0c;考虑用bfs&#xff08;没试过单向&#xff0c;但是系数很大&#xff09; 更详细的解答 下面是代码理解&#xff08;注释版&#xff09; // Problem: // P1032 [NOIP2002 提高组] 字串变换 // …

0206-1-网络层

第 4 章 网络层 网络层提供的两种服务 虚电路服务 数据报服务 概要: 虚电路服务与数据报服务的对比 网际协议 IP 网际协议 IP 是 TCP/IP 体系中两个最主要的协议之一。与 IP 协议配套使用的还有四个协议&#xff1a; 地址解析协议 ARP (Address Resolution Protocol)逆地…

svg图片构造QGraphicsSvgItem对象耗时很长的问题解决

目录 1. 问题的提出 2. 问题解决 1. 问题的提出 今天通过一张像素为141 * 214&#xff0c;大小为426KB的svg格式的图片构造QGraphicsSvgItem对象&#xff0c;再通过Qt的Graphics View Framework框架&#xff0c;将QGraphicsSvgItem对象显示到场景视图上&#xff0c;代码如下&…

windows安装Mysql解压版

windows安装Mysql解压版 一、下载mysql-8.0.36-winx64.zip二、解压三、配置3.1. 添加环境变量&#xff1a;新建MYSQL_HOME3.2.如何验证是否添加成功&#xff1a;必须以管理员身份启动3.3. 初始化MySQL&#xff1a;必须以管理员身份启动3.4. 注册MySQL服务&#xff1a;必须以管理…

Java面试第一站:计算机网络基础知识

该系列会持续更新&#xff0c;关注我&#xff0c;第一时间获取我的最新动态哟 Java面试中&#xff0c;经常会问到跟计算机网络知识相关的考点&#xff0c;有的小伙伴不是很明白。考察网络知识有什么意义&#xff1f; 因为编程的时候&#xff0c;多数的情况下是不用我们来编写 …

人工智能技术应用笔记(二):OpenAI SORA文生视频模型技术报告全文中英对照 (GPT4翻译+人工润色)

目录 Video generation models as world simulators&#xff08;视频生成模型作为世界模拟器&#xff09; Turning visual data into patches &#xff08;将视觉数据转换为图像块&#xff09; Video compression network &#xff08;视频压缩网络&#xff09; Spacetim…

WouoUI-PageVersion 一个用于快速构建具有丝滑OLED_UI动画的项目

WouoUI-PageVersion 写在前面 简介&致谢 Air001的TestUI例子的b站的演示视频 Air001的LittleClock例子的b站演示视频: https://www.bilibili.com/video/BV1J6421g7H1/ Stm32的TestUI例子的b站演示视频: https://www.bilibili.com/video/BV1mS421P7CZ/ 所有演示的工程文…

MySQL数据库基础(九):SQL约束

文章目录 SQL约束 一、主键约束 二、非空约束 三、唯一约束 四、默认值约束 五、外键约束&#xff08;了解&#xff09; 六、总结 SQL约束 一、主键约束 PRIMARY KEY 约束唯一标识数据库表中的每条记录。主键必须包含唯一的值。主键列不能包含 NULL 值。每个表都应该有…

网络编程_TCP通信综合练习:

1 //client&#xff1a;&#xff1a; public class Client {public static void main(String[] args) throws IOException {//多次发送数据//创建socket对象,填写服务器的ip以及端口Socket snew Socket("127.0.0.1",10000);//获取输出流OutputStream op s.getOutput…

云手机受欢迎背后的原因及未来展望

随着办公模式的演变&#xff0c;云手机的热潮迅速兴起。在各种办公领域&#xff0c;云手机正展现出卓越的实际应用效果。近年来&#xff0c;跨境电商行业迎来了蓬勃发展&#xff0c;其与国内电商的差异不仅体现在整体环境上&#xff0c;更在具体的操作层面呈现出独特之处。海外…

OpenAI划时代大模型——文本生成视频模型Sora作品欣赏(二)

Sora介绍 Sora是一个能以文本描述生成视频的人工智能模型&#xff0c;由美国人工智能研究机构OpenAI开发。 Sora这一名称源于日文“空”&#xff08;そら sora&#xff09;&#xff0c;即天空之意&#xff0c;以示其无限的创造潜力。其背后的技术是在OpenAI的文本到图像生成模…

AES加密中的CBC和ECB

目录 1.说明 2.ECB模式&#xff08;base64&#xff09; 3.CBC模式 4.总结 1.说明 AES是常见的对称加密算法&#xff0c;加密和解密使用相同的密钥&#xff0c;流程如下&#xff1a; 主要概念如下&#xff1a; ①明文 ②密钥 用来加密明文的密码&#xff0c;在对称加密算…

OpenCV 入门讲解

OpenCV 入门讲解 OpenCV&#xff08;Open Source Computer Vision Library&#xff09; 是一个开源的计算机视觉库&#xff0c;它提供了许多高效实现计算机视觉算法的函数&#xff0c;从基本的滤波到高级的物体检测都有涵盖。OpenCV 使用 C/C 开发&#xff0c;同时也提供了 Pyt…

【HarmonyOS】鸿蒙开发之Button组件——第3.4章

按钮类型 Capsule&#xff08;默认值&#xff09;&#xff1a;胶囊类型 Button("默认样式").height(40)//高度.width(90)//宽度.backgroundColor(#aabbcc)//背景颜色运行结果: Normal&#xff1a;矩形按钮&#xff0c;无圆角 Button({type:ButtonType.Normal}){Te…

Cesium 问题——加载 gltf 格式的模型之后太小,如何让相机视角拉近

文章目录 问题分析问题 刚加载的模型太小,如何拉近视角放大 分析 在这里有两种方式进行拉近视角, 一种是点击复位进行视角拉近一种是刚加载就直接拉近视角// 模型三加载 this.damModel = new Cesium.Entity({name: "gltf模型",position:</

js设计模式:单例模式

作用: 保证一个类只有一个实例,并且提供一个全局的访问位置。 可以用来实现全局的一些状态管理或者独一无二的数据 示例: class Wjt{constructor(name,idNumber,gender){this.name namethis.idNumber idNumberthis.gender gender}//可以直接使用Wjt调用的静态方法static …

java 培训班预定管理系统Myeclipse开发mysql数据库web结构jsp编程servlet计算机网页项目

一、源码特点 java 培训班预定管理系统是一套完善的java web信息管理系统 采用serlvetdaobean&#xff0c;对理解JSP java编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开发。开发环境为TOMCAT7.0,Myeclipse8.5开发&#xf…

【Jvm】性能调优(上)线上问题排查工具汇总

文章目录 一.互联网概念1.产品闭环和业务闭环2.软件设计中的上游和下游3.JDK运行时常量池 二.CPU相关概念1.查询CPU信息2.CPU利用率&#xff08;CPU utilization&#xff09;和 CPU负载&#xff08;CPU load&#xff09;2.1.如何理解CPU负载2.2.top命令查看CPU负载均值2.3.CPU负…

进程链信任-父进程欺骗

文章目录 前记普通权限的父进程欺骗ShllCode上线进程提权基础进程提权注入 前记 父进程欺骗作用&#xff1a; 进程链信任免杀进程提权 检测&#xff1a; etw 普通权限的父进程欺骗 #include<stdio.h> #include<windows.h> #include <TlHelp32.h>DWORD …