Hive常用的优化方式
fetch抓取
hive-default.xml.template
hive.fetch.task.conversion
默认为none,查询语句都会使用MR,将none改为more,全局查找、字段查找、limit查询语句将不走MR,效率显著提升。
local本地模式
通过本地模式在单台机器上处理所有的任务,对于对于小数据集,执行时间明显缩短,多用于测试,不放在Yarn去运行。
//适当时候开启本地MR
hive.exec.mode.local.auto = true
//设置local MR的最大输入数据量(默认128M)
set hive.exec.mode.local.auto.inputbytes.max = 50000000
//设置local MR最大输入文件个数(默认4)
set hive.exec.mode.local.auto.input.files.max = 10
表的优化
1)大小表join
新版hive对小表放在左边和右边的区别已经不大,可在map端使用group让小的维度表(<1000条)先进内存,在map端完成reduce。
2)大表join大表
空key过滤,类似于过滤倾斜/异常数据,因为相同key的会发送到相同的reducer上,从而导致内存不够。
3)MapJoin
//默认为true
set hive.auto.convert.join = true
//默认25M以下为小表
set hive.mapjoin.smalltable.filesize = 25000000
不符合/不指定MapJoin条件的,Hive会将Join转换成Common Join,即reduce阶段完成join,容易发生数据倾斜。开启后,可以通过MapJoin把小表全部加载到内存在map端进行join,避免reduce处理。
4)Group By
//是否在map端进行聚合,默认true
hive.map.aggr = true
//在Map端进行聚合操作的条目数目
hive.groupby.mapaggr.checkinterval = 100000
设定为true的时候,产生两个MR job,第一个MR job的输出结果随机分不到reduce中,每个reduce做部分聚合操作,并输出结果,负载均衡,第二个MR job再根据预处理的数据结果按照group by把相同key分布到一个reduce,完成最终聚合操作。
5)Count(Distinct)
count(distinct) —> count +group by
数据量大的时候,由于count(distinct)操作需要用一个reduce task来完成,这一个reduce需要处理的数据量太大,就会导致整个job很难完成,可以通过group by去重后再去count。
6)笛卡尔积
尽量避免笛卡尔积。
7)行列过滤
列:只select需要的列,尽量使用分区过滤。
行:外关联时,如副表过滤条件写在where后面,就会先关联全表再过滤,可以先使用子查询过滤再关联。
8)动态分区调整
//开启动态分区,默认true
hive.exec.dynamic.partition = true
//关闭严格模式,严格模式必须指定至少一个分区为静态分区,非严格模式允许所有字段使用动态分区
hive.exec.dynamic.partition.mode = nonstrict
//所有执行MR的节点上,最大一共可创建多少个动态分区
hive.exec.max.dynamic.partitions = 1000
//每个执行MR的节点上,最大可以创建多少个动态分区(一年的天则需>365)
hive.exec.max.dynamic.partitions.pernode = 100
//整个MR job中,最大可以创建多少个HDFS文件
hive.exec.max.created.files = 100000
//有空分区时,是否抛出异常,一般不需要设置
hive.error.on.empty.partition = false
解决数据倾斜
1)设置合理的Map数
maptask的个数取决于输入文件大小、文件切片大小,集群设置的文件块的大小。文件的大小远远小于128M时,合并小文件,减少map数,但是也不是每个map处理接近128M的切片文件就行了,当一个文件127M,字段很少,但记录却又千万条,当处理逻辑复杂时就比较耗时,此时要增加map数。
2)小文件合并
set hive.input.format = org.apache.hadoop.hive.ql.io.CombineHiveInputFormat
map执行前合并小文件,减少map数,CombineHiveInputFormat(系统默认格式)具有合并小文件的功能,HiveInputFormat没有对小文件合并的功能。
3)复杂文件增加Map数
当输入文件很大,任务逻辑复杂,导致map执行非常慢的时候,可以考虑增加map数,减少每个map处理数据量的大小,提高任务执行效率。
设置切片大小公式:
computeSliteSize(Math.max(minSize,Math.min(maxSize,blocksize))) = blocksize = 128M
//设置最大切片大小为100字节
set mapreduce.input.fileinputformat.split.maxsize = 100
4)合理设置Reduce数
//每个reduce处理的数据量,默认256M
hive.exec.reducers.bytes.per.reducer=256000000
//每个任务最大的reduce数,默认1009
hive.exec.reducers.max=1009
计算reducer数的公式:
N=min(参数2,总输入数据量/参数1)
并行化
//打开任务并行执行
hive.exec.parallel = true
//同一个sql允许最大并行度
set hive.exec.parallel.thread.number = 16(8)
并非互相依赖的阶段可以并行执行,这样可能使得job的执行时间缩短(配置支持的前提下)。
严格模式
hive.mapred.mode —> 设置为nostrict
开启严格模式有3种类型的查询是禁止的:
1)分区表,除非where中含分区字段过滤条件,否则不允许执行
2)order by语句,必须使用limit语句
3)笛卡尔积,默认不能使用笛卡尔积,可以使用1=1强制关联
JVM重用
mapred-site.xml —> mapreduce.job.jvm.numtasks
优点:JVM实例在同一job中重复使用N次,减少开销。
缺点:JVM重用将一直占用使用到的task卡槽,所有的task完成后才会释放,若某个job的某几个reduce task很长,name空闲的task也无法继续使用。
适用于小文件/task特别多的场景。
推测执行
待了解。