优化思路:
hive性能优化时,把HiveQL当做M/R程序来读,即从M/R的运行角度来考虑优化性能,从更底层思考如何优化运算性能,而不仅仅局限于逻辑代码的替换层面。
列裁剪
Hive 在读数据的时候,可以只读取查询中所需要用到的列,而忽略其它列
分区裁剪
可以在查询的过程中减少不必要的分区,不用扫描全表。
合理设置reduce的数量
使大数据量利用合适的reduce数;使单个reduce任务处理合适的数据量。
在不指定reduce个数的情况下,Hive会猜测确定一个reduce个数,基于以下两个设定:
参数1:hive.exec.reducers.bytes.per.reducer(每个reduce任务处理的数据量,在Hive 0.14.0及更高版本中默认为256M)
参数2:hive.exec.reducers.max(每个任务最大的reduce数,在Hive 0.14.0及更高版本中默认为1009)
计算reducer数的公式: N = min( 参数2,总输入数据量 / 参数1 )
job并行运行设置
带有子查询的hql,如果子查询间没有依赖关系,可以开启任务并行,设置任务并行最大线程数。
hive.exec.parallel (默认是false, true:开启并行运行)
hive.exec.parallel.thread.number (最多可以并行执行多少个作业, 默认是 8)
小文件的问题优化
如果小文件多,在map输入时,一个小文件产生一个map任务,这样会产生多个map任务;启动和初始化多个map会消耗时间和资源,所以hive默认是将小文件合并成大文件。
set hive.input.format=org.apache.hadoop.hive.ql.io.CombineHiveInputFormat; (默认)
如果map输出的小文件过多,hive 默认是开启map 输出合并。
set hive.merge.mapfiles=true (默认是 true)
hive.merge.size.per.task(合并文件的大小,默认 256M)
hive.merge.smallfiles.avgsize(文件的平均大小小于该值时,会启动一个MR任务执行merge,默认16M )
如果reduce输出的小文件过多,hive需要手动设置开启reduce输出合并。
set hive.merge.mapredfiles=true (默认是 false)
hive.merge.size.per.task(合并文件的大小,默认 256M)
hive.merge.smallfiles.avgsize(文件的平均大小小于该值时,会启动一个MR任务执行merge,默认16M )
join 操作优化
join 原则:
1)小表放左;
2)多表join,如果join字段一样,只生成一个job 任务;
3)Join 的字段类型要一致。
MAP JOIN操作
如果你有一张表非常非常小,而另一张关联的表非常非常大的时候,你可以使用mapjoin此Join 操作在 Map 阶段完成,不再需要Reduce,hive默认开启mapjoin。
hive的数据倾斜优化
数据倾斜的原因
key分布不均匀
业务数据本身的特性
某些SQL语句本身就有数据倾斜
数据倾斜的表现
任务进度长时间维持在99%(或100%),查看任务监控页面,发现只有少量(1个或几个)reduce子任务未完成。因为其处理的数据量和其他reduce差异过大。
单一reduce的记录数与平均记录数差异过大,通常可能达到3倍甚至更多。 最长时长远大于平均时长。
通用解决方案——参数调节
对于group by 产生倾斜的问题
set hive.map.aggr=true; (默认是 true)
开启map端combiner,减少reduce 拉取的数据量。
set hive.groupby.skewindata=true; (默认是 false)
有数据倾斜的时候进行负载均衡,当选项设定为 true,生成的查询计划会有两个 MR Job。第一个 MR Job 中,Map 的输出结果集合会随机分布到 Reduce 中,每个 Reduce 做部分聚合操作,并输出结果,这样处理的结果是相同的 Group By Key 有可能被分发到不同的 Reduce 中,从而达到负载均衡的目的;第二个 MR Job 再根据预处理的数据结果按照 Group By Key 分布到 Reduce 中(这个过程可以保证相同的 Group By Key 被分布到同一个 Reduce 中),最后完成最终的聚合操作。
如果开启负载均衡:
set hive.groupby.skewindata=true
SQL 语句调节:
大表Join大表:
非法数据太多,比如null。
假如null值没有用处的话,可以将null值先过滤掉,再进行 union
把空值的key变成一个字符串加上随机数,把倾斜的数据分到不同的reduce上,由于null值关联不上,处理后并不影响最终结果。
count distinct 数据倾斜
在执行下面的SQL时,即使设置了reduce个数也没用,它会忽略设置的reduce个数,而强制使用1。这唯一的Reduce Task需要Shuffle大量的数据,并且进行排序聚合等处理,这使得它成为整个作业的IO和运算瓶颈。
设置多个reduce时,在reduce阶段可以多个reduce处理数据,而不是只有一个reduce处理数据。