Hive调优与数据倾斜优化
一、Hive调优策略
- 架构调优
1、执行引擎:Hive默认使用的是MR,可以换为Tez,Tez将多个mapReduce任务合并成一个较大的DAG任务,减少mapreduce迭代过程中文件存储,其他的引擎可以是spark,flink等;
2、分区分桶表:对于一张较大的表,将其设计成分区表可以提高查询性能,一般是日期;分桶表的组织方式是将HDFS上的文件分割成多个文件,分桶表可以加快数据的抽样,提升JOIN的性能;
3、文件存储格式:Hive默认使用TextFile,可以指定为SequenceFile,Parquet,ORC等格式;其中Parquet等列式存储需要TextFile作为跳板;
4、文件压缩格式:减少map和reduce之间的数据传输,从而可以提升查询性能--开启压缩 SET hive.exec.compress.intermediate=true
-- 中间结果压缩
SET hive.intermediate.compression.codec=org.apache.hadoop.io.compress .SnappyCodec
-- 输出结果压缩
SET hive.exec.compress.output=true;
SET mapreduce.output.fileoutputformat.compress.codec = org.apache.hadoop.io.compress.SnappyCodc - 参数调优
1、使用本地模式:当Hive处理小数据量时,启动分布式查询会浪费时间,Hive支持将作业转为本地模式,需要开启一下配置SET hive.exec.mode.local.auto=true
2、严格模式:主要包含三种类型的SQL,一旦执行将报错,分别是查询分区表时不限定分区列的语句;两表JOIN产生笛卡尔积的语句;使用order by排序时没有limit语句
SET hive.mapred.mode=nostrict
3、JVM重用:默认情况下hadoop会为每一个map task和reduce task启动一个JVM,这样可以并行执行任务。当某个task是轻量级的作业时,JVM的启动要比作业的执行时间还要长。此时hadoop可以重用JVM,通过共享JVM以串行的方式运行task;当然存在不好的地方是,启动的JVM会一直占用task插槽,直到任务运行结束才释放,比如存在不平衡的job,少数几个map或者reduce task执行时间长的话该JVM会空闲。
SET mapreduce.job.jvm.numtasks=4
4、合并小文件
--在map task执行前合并小文件
set hive.input.format=org.apache.hadoop.hive.ql.io.CombineHiveInputFo rmat;
--在reduce结束时合并小文件
SET hive.merge.mapfiles = true;
SET hive.merge.mapredfiles = true;
SET hive.merge.size.per.task = 268435456;
SET hive.merge.smallfiles.avgsize = 16777216;5、Fetch模式:Hive中对于某些查询不必使用MapReduce计算,可以简单的读取对应的存储文件,输出结果, hive.fetch.task.conversion=more
- SQL调优
1、列裁剪和分区裁剪
2、sort by代替order by
3、group by代替count(distinct col)
4、处理空值与无意义的值
5、单独处理热KEY
6、JOIN优化
7、GROUP BY配置调整--map端预聚合:即在map端启动一个combiner做预聚合,减少shuffle的数据量,减少io传输
set hive.map.aggr=true
--倾斜均衡配置项:group by时某些key的数据量过大,会发生数据倾斜; 原理为启动两个MR,第一个job将map的数据随机写入reducer,做部分聚合,第二个job在进行聚合
set hive.group.skewindata=true
map数处理:map数量主要和输入文件总数,输入文件大小,hdfs文件快大小;map数量并不是越多越好,一个任务有很多小文件,每个文件会启动一个map任务,会造成资源浪费;当一个文件接近128M时,假设它字段很少,但行数很多,但其处理逻辑比较复杂,使用就一个map去做,性能也不会很好;
reduce数处理:可以设置set mapred.reduce.tasks=n,不设置会自动下推,当然reduce也不是越多越好,reduce太多,生成的小文件越多,对hdfs造成压力;reduce数量太少,每个reduce要处理很多数据,容易拖慢运行时间或者造成OOM
二、数据倾斜出现场景以及解决
总的来说,出现数据倾斜主要两个原因:一是任务中需要处理大量相同的key的数据;二是任务读取不可分割的大文件;一个发生在reduce中,一个发生在map中,map中一般由于文件不可切分,Gzip格式的
- 空值引发的数据倾斜
有时业务数据存在大量的null值或者无意义的值,在JOIN中,所有的null值将分配到一个reduce中,必然产生数据倾斜--过滤null值,不参与处理逻辑
if(col is null, concat('rand_', rand()))
--join
select * from a left join b on case when a.col_name is null then concat('rand_', rand()) else a.col_name end = b.col_name - 不同数据类型产生的数据倾斜
- 数据膨胀引发的数据倾斜
- 不可拆分大文件引发数据倾斜
- 表连接时发生的数据倾斜:1)大表join小表:map join,需要关注小表数据量 2)裁剪,二次聚合,热key分离,key值采样
- GROUP BY 引发的数据倾斜
- SQL语句自身存在的数据倾斜:collect_set,调整reduce的内存大小