Hive 调优
个人总结Hive调优分为两大类,参数调优和SQL调优
参数调优
0. 比较有用的参数
--设置用户使用队列
set mapreduce.job.queuename=root.paas_test;-- 设置作业名
set mapred.job.name = HV_INS_ORDER_INFO_D(${hivevar:statis_date});--让CLI打印出字段名称
set hive.cli.print.header=true;
1. 控制map/reduce的内存和核数
这个参数有时候用的比较多,比如报oom,堆内存溢出等,数量过大,处理慢等可以适当增加这个值
set mapreduce.map.memory.mb=3072;
set mapreduce.map.cpu.vcores=1;
set mapreduce.reduce.memory.mb=6144;
set mapreduce.reduce.cpu.vcores= 2 ;
2. 控制reduce个数的参数
--控制每个redcue处理量的参数
set hive.exec.reducers.bytes.per.reducer=1000000000;--控制单个job最大redcue个数
set hive.exec.reducers.max=2999;--直接指定单个job多少个reduce个数
set mapreduce.job.reduces=10; --或者用老版本的set mapred.reduce.tasks
3. 控制map个数的参数,配合小文件治理一起使用
set mapred.max.split.size=256000000 ;
set mapred.min.split.size=32000000 ;
set mapred.min.split.size.per.node=32000000 ;
set mapred.min.split.size.per.rack=32000000 ;
4. 小文件治理参数
--开启小文件合并,以及小文件大小
set hive.input.format = org.apache.hadoop.hive.ql.io.CombineHiveInputFormat;
set hive.merge.mapfiles = true ;
set hive.merge.mapredfiles = true;
set hive.merge.smallfiles.avgsize=32000000;
set hive.merge.size.per.task=25600000;--控制map的输入大小,实现真正的小文件合并
set mapred.max.split.size=256000000 ;
set mapred.min.split.size=32000000 ;
set mapred.min.split.size.per.node=32000000 ;
set mapred.min.split.size.per.rack=32000000 ;
5. 设置map/reduce的task实例的最大失败尝试次数
set mapreduce.map.maxattempts=4; --老版本用:mapred.map.max.attempts
set mapreduce.reduce.maxattempts =4; ---老版本用 :mapred.reduce.max.attempts
6. 设置APPmaster的相关内存/CPU,使用相对较少,一般报appmaster内存溢出可以使用;
set yarn.app.mapreduce.am.resource.mb=6144;
set yarn.app.mapreduce.am.resource.cpu-vcores=2;
--补充即当 AppMaster 失败2次之后,运行的任务将会失败。
Set mapreduce.am.max-attempts=2;(官方默认值)
7. 关于是否开启map/redduce 推测执行的参数,建议跟随集群层面即可
set mapreduce.map.speculative=true ;
set mapreduce.reduce.speculative=true ;
set mapreduce.job.speculative.speculative-cap-running-tasks=0.1 ;
8. 对于需要并行执行的任务,开启并行
--是否开启job并行执行 ,默认false;
set hive.exec.parallel=true;--同一段sql最多可以并行执行多少作业job
set hive.exec.parallel.thread.number=8;
9. 动态分区相关参数
--(默认false),表示开启动态分区功能
set hive.exec.dynamic.partition =true;--默认strict模式,表示用户必须指定至少一个静态分区字段,以防用户覆盖所有分区。
--Nonstrict模式表示允许所有分区都可以直接动态分区;
set hive.exec.dynamic.partition.mode = nonstrict;--默认100,一般可以设置大一点,比如1000,表示每个maper或reducer可以允许创建的最大动态分区个数,超出则会报错
set hive.exec.max.dynamic.partitions.pernode=100;--表示一个动态分区语句可以创建的最大动态分区个数,超出报错
set hive.exec.max.dynamic.partitions =1000;--(默认) 全局可以创建的最大文件个数,超出报错。
set hive.exec.max.created.files =10000;
10. mapjoin优化参数
将小表上传到分布式缓存,然后分发到大表各个maptask的节点
--mapjoin优化参数,注意mapjoin的使用场景;
set hive.auto.convert.join=true;
set hive.mapjoin.smalltable.filesize= 25000000;
11. groupby参数优化
--开启mapside聚合,建议开启
set hive.map.aggr=true;--负载均衡,慎用,尤其和上面参数一起使用时可能造成错误的统计结果
set hive.groupby.skewindata= false;
12. 向量化默认,慎用,有时候会变慢;
set hive.vectorized.execution.enabled=true;
13. 了解即可,关于Hadoop2.x的jvm重用机制的uber模式
--是否启用uber功能
set mapreduce.job.ubertask.enable=false;
set mapreduce.job.ubertask.maxmap=9;
set mapreduce.job.ubertask.maxreduces=1;
set mapreduce.job.ubertask.maxbytes=dfs.block.size;
14. 本地模式
set hive.exec.mode.local.auto=true;
set hive.exec.mode.local.auto.inputbytes.max=268217728;
set hive.exec.mode.local.auto.tasks.max=10;
15. 严格模式
set hive.mapred.mode=nonstrict;
16. fetch抓取模式
set hive.fetch.task.conversion=more;
17. limit限制
-- 官方默认false
set hive.limit.optimize.enable=true;-使用limit做数据的子集查询时保证的最大行数据量
set hive.limit.row.max.size= 100000;--在使用limit做数据子集查询时,可抽样的最大文件数
set hive.limit.optimize.limit.file= 10;set hive.limit.optimize.fetch.max=50000;
18. 常用命令
--1.手动通过客户端杀死任务
yarn application -kill application_1639740855307_4111216
hadoop job -kill job_1639740855307_4111216
hadoop job -kill-task attempt_1639740855307_4111291_r_000001_1--2.给在跑的任务换个队列跑
yarn application -movetoqueue application_1639740855307_3934397 -queue root.ga_mid
19. 偶尔可能用的参数
--1.查询加个表头(特殊场景使用)set hive.cli.print.header=true;--2.给作业加个名称,统一名称,很香的set mapred.job.name='xxxxxx';--3.如果 DROP TABLE/VIEW/PARTITION/INDEX/TEMPORARY FUNCTION 指定了一个不存在的表/视图,不要报错set hive.exec.drop.ignorenonexistent=false;
20. 分桶表的使用
set hive.enfore.bucketing =true;
set hive.enforce.sorting=true;
set hive.optimize.bucketingsorting=true;
21. 开启smb-mapjoin
单纯适合数据量大的情况,对于数据倾斜的优化有限
set hive.optimize.bucketmapjoin = true;
set hive.auto.convert.sortmerge.join=true;
set hive.input.format=org.apache.hadoop.hive.ql.io.BucketizedHiveInputFormat;
set hive.optimize.bucketmapjoin.sortedmerge = true;
22. skewedjoin数据倾斜优化
只适合inner join,而且和parallel一起用会丢数据,少用,可以手写
set hive.optimize.skewjoin=true;
set hive.skewjoin.key =5000000;
23. 修复分区表
--修复分区
MSCK [REPAIR] TABLE table_name [ADD/DROP/SYNC PARTITIONS];
msck repair table s_test.ods_star_sample_data_a_d;---分区表加字段
alter table default.testparquet add columns(c8 string) cascade;
24. 运维相关,稍微了解一下
--1.表示maptask至少完成50%以上,才开始为reduce申请资源吗,执行reducetask。实际比比如我们公司生产设置的1。
set mapreduce.job.reduce.slowstart.completedmaps=0.5 ;---2.把一台物理机的多少资源分配给Nodemanager,比如64core/256G的机器,我们分配给nm 48core/195G
set yarn.nodemanager.resource.memory-mb=195*1024*1024*1024
set yarn.nodemanager.resource.cpu-vcores=48---3.给每个container分配的内存范围,CPU范围
yarn.scheduler.minimum-allocation-mb=3072;
yarn.scheduler.maximum-allocation-mb=64*1024;
yarn.scheduler.minimum-allocation-vcores=1;
yarn.scheduler.maximum-allocation-vcores=32;---4.严格模式开启
set hive.mapred.mode=strict;
SQL调优
SQL调优也可以分成三部分,过滤调优,聚合调优,join调优
过滤调优
尤其要关注的是过滤条件使用的位置,个人总结是这样的:
- inner join 放在哪都一样
- left/right join 主表条件放在where中,从表条件放在on中
- full join 放在哪都不生效,建议使用子查询
分区裁剪
注意分区裁剪是发生在map之前的。
列裁剪
最好是和列存储格式配合使用,比如orc,parquet。
就是避免select * 这种情况。
注意,列裁剪不会减少开始时候的map数量,但是会减少中间和结果的数据量。
谓词下推
就是条件写在where 和 on 里有什么区别。能过滤的先过滤,就是这样。
聚合优化
count(distinct xxx)
为了保证全局的一致性,count(distinct xxx)只会启用一个reduce来执行,对于数据量特别大的情况下的话,就会很慢。这时候我们就可以采用预聚合的方式来环境最好reduce的压力(group by + count)
order by
为了保证全局的一致性,order by也只会启用一个reduce来执行。
在严格模式下,order by 必须加limit限制
对于order by 我们通过使用子查询,在每个 Reduce 中进行排序后,各自取得前 N 个数据,然后再对结果集进行全局排序,最终取得结果。
--没有优化版本,全局排序跑的很慢
SELECTt2.dept_nm,t1.db ,table_name ,SUM(t1.filesize_mb)/1024.0 as filesize_gb
FROM mobdi_test.tmp_fsimage_info_log_clean_result t1
LEFT JOIN _bg_devops.dept_db_relationships t2
ON t1.db =t2.db_nmmob
WHERE t1.stat_day ='20230221'AND t1.modificationtime < '2022-04-25'AND t1.accesstime < '2022-04-25'
GROUP BYt2.dept_nm,t1.db ,table_name
ORDER BY filesize_gb desc LIMIT 100;
--优化版本:通过使用子查询,在每个 Reduce 中进行排序后,各自取得前 N 个数据,然后再对结果集进行全局排序,最终取得结果。
SELECTdept_nm,db,table_name,filesize_gb
FROM
(selectdept_nm,db,table_name,filesize_gbfrom( SELECTt2.dept_nm,t1.db ,table_name ,SUM(t1.filesize_mb)/1024.0 as filesize_gbFROM mobdi_test.tmp_fsimage_info_log_clean_result t1LEFT JOIN mob_bg_devops.dept_db_relationships t2ON t1.db =t2.db_nmWHERE t1.stat_day ='20230221'AND t1.modificationtime < '2022-04-25'AND t1.accesstime < '2022-04-25'GROUP BYt2.dept_nm,t1.db ,table_name
)T1
distribute by filesize_gb sort by filesize_gb desc limit 100 ) T2
ORDER BY filesize_gb LIMIT 100;
Multiple Inserts
使用多插入(Multiple Inserts)语法也叫 多表 插入 (Multi Table Insert)。多插入(Multiple Inserts)将扫表次 数降 低到 最小 ,降低插入总耗时。之所以说是总耗时,其实并没有降低写入的数据量或者降低写入时间,而是降低扫表时间,将多次扫表合并为一次扫表。
Hive 官网给出通过查询 insert 表的语法格式:
Standard syntax:
INSERT OVERWRITE TABLE tablename1 [PARTITION (partcol1=val1,
partcol2=val2 ...) [IF NOT EXISTS]] select_statement1 FROM from_statement;
INSERT INTO TABLE tablename1 [PARTITION (partcol1=val1, partcol2=val2 ...)]
select_statement1 FROM from_statement;-- Hive extension (multiple inserts):
FROM from_statement
INSERT OVERWRITE TABLE tablename1 [PARTITION (partcol1=val1,
partcol2=val2 ...) [IF NOT EXISTS]] select_statement1
[INSERT OVERWRITE TABLE tablename2 [PARTITION ... [IF NOT EXISTS]]
select_statement2]
[INSERT INTO TABLE tablename2 [PARTITION ...] select_statement2] ...;
FROM from_statement
INSERT INTO TABLE tablename1 [PARTITION (partcol1=val1,
partcol2=val2 ...)] select_statement1
[INSERT INTO TABLE tablename2 [PARTITION ...] select_statement2]
[INSERT OVERWRITE TABLE tablename2 [PARTITION ... [IF NOT EXISTS]]
select_statement2] ...;-- Hive extension (dynamic partition inserts):
INSERT OVERWRITE TABLE tablename PARTITION (partcol1[=val1],
partcol2[=val2] ...) select_statement FROM from_statement;
INSERT INTO TABLE tablename PARTITION (partcol1[=val1], partcol2[=val2] ...)
select_statement FROM from_statement;
知识点 1:从 Hive 0.13.0 开始,可以通过使用 TBLPROPERTIES (“immutable”=“true”)创建表来使其不可变。默认值为“不可变”=“假”。如果任
何数据已经存在,则 INSERT INTO 行为将被禁止到不可变表中,但如果不可变表为空,则 INSERT INTO 仍然有效。INSERT OVERWRITE 的行为不受“不可变”表属性的影响。
join的优化
对于join的优化,主要就是为了避免shuffle。