问题描述
有很多刚学习的小伙伴,想学习参数优化,又不知道有哪些参数,如何优化。
给大家,说明思路。
1.set 你知道在这里找,说明你知道实际生效的作用
2.hive-site.default.xml,你知道在这里找,说明你知道这个配置文件的作用(cdp-hive3.1的部分配置hive官网都没有。。在clouder的官网)
3.官网。官网永远是学习最好的地方,不用多说
Configuration Properties - Apache Hive - Apache Software Foundation
下面再详细说下各个参数的优化及实操过程。
一、分区裁剪,列裁剪
思想:就是减少读取的数据量。
比如a 1000w b 1000w 这两个表join耗时,但是b过滤只有1w了这个时候join就很简单了。
比如 a 有100个字段 b有100个字段,其实我们只需要a b的几个字段,如果还是用*那么导致读取的数据量很多
关于分区裁剪 其实就是谓词下推,目前hive版本都支持的,就是把where条件推到下游。
二、count(distinct) 和group by
这个很多人都说的都是distinct只有一个reduce 会把所有数据放到一个reduce导致处理的很慢?
那么为什么只有一个reduce呢?有没有人想过,我不是可以设置reduce个数 reduce处理量么?
我看到一个说法是:因为distinct 内部会给所有数据进行hash 然后排序,这样只能在一个reduce里。
那么group by 呢? 这个是可以手动控制map数和reduce个数的。
同时注意参数
map端预聚合 理解为combiner
set hive.map.aggr=true --Whether to use map-side aggregation in Hive Group By queries
map端聚合的数目条数
set hive.groupby.mapaggr.checkinterval=100000--Number of rows after which size of the grouping keys/aggregation classes is performed
倾斜处理 类似与加盐打散 a 变成 a1 a2 a3 ...a9 然后合并为a
set hive.groupby.skewindata=true --Whether there is skew in data to optimize group by queries
三、分区 分桶
这个目的也是为了将文件切分。读取的文件数量少,自然速度就快
这个懒得说了,一般来说数据量多一点就可以分区,然后特别多的话可以分桶
四、并行
set hive.exec.parallel=true; //默认关闭,可以开启并发执行
set hive.exec.parallel.thread.number=8; //同一个sql允许最大并行度,默认为8
说下这两个参数,顾名思义并行处理任务,大部分情况下能够加快数据处理时间,特别是多个表join ,例如 (a join b) ab join (c join d) cd on ab.key=cd.key。
但是注意 这个并行开启了,客户端时看不了日志的,例如stage task成功了几个失败了几个,
而且我由此遇到过一个任务不开并行能够跑成功,开了跑了一半必失败。。。
而且开并行对资源的耗费也比较大,看情况慎用
五、mapjoin
可以看到大多数文章都逃不过mapjoin这个说法,那么mapjoin是什么呢?其实就是将这个表的数据分发到各个节点或者map任务中。
注意这句话!!mapjoin 无shuffle 无reduce!!可能很多人见过这句话,但是不知道话会有什么作用,比如有的用了mapjoin还想调整reduce的个数?门都没有。
set hive.auto.convert.join=true; //false in 0.7.0 to 0.10.0; true in 0.11.0 and later
set hive.auto.convert.join.noconditionaltask=true;
set hive.auto.convert.join.noconditionaltask.size=10000000; // 10M
set hive.mapjoin.smalltable.filesize=25000000; //小表阈值25M--关于 noconditionaltask
Whether Hive enables the optimization about converting common join into mapjoin based on the input file size. \n" + "If this parameter is on, and the sum of size for n-1 of the tables/partitions for a n-way join is smaller than the\n" + "specified size, the join is directly converted to a mapjoin (there is no conditional task).查了下其他人的翻译,各有千秋这个翻译靠谱点。Hive在基于输入文件大小的前提下将普通JOIN转换成MapJoin,并是否将多个MJ合并成一个,多个MJ合并成一个MJ时,其表的总的大小须小于该值,同时hive.auto.convert.join.noconditionaltask必须为true
小表 odsiadata.label_dict -- 29532=28.8 K cnt=596
大表 odsiadata.cooperation_label_entity -- 310M cnt=4,744,974
那么怎么知道mapjoin起作用了吗?
explain
select a.*,b.*
from odsiadata.cooperation_label_entity a
join odsiadata.label_dict b
on a.label_key=b.label_key;采用默认参数 即 auto.mapjoin=true 和 .smalltable.filesize=25M
结果是mapjoin 大表left join 小表也会自动mapjoin
explain
select a.*,b.*
from odsiadata.label_dict a
left join odsiadata.cooperation_label_entity b
on a.label_key=b.label_key
采用默认参数,注意这里 小表作为主表,map join失效 会有reduce
那如果我现在就不想让他mapjoin呢?或者说我怎么知道哪个参数真正起作用了?
上图有个hive.auto.convert.join.noconditionaltask.size=10000000=10M
还有个hive.mapjoin.smalltable.filesize=25000000=25M
如果我的小表大小是20M 是走mapjoin还是reduce呢?这个问题你们可以问下那些博主有几个能答出来。
然后我们这个表的大小到底是多少呢?
可以看到
大表=325492973 =310M
小表=29532=28.8k
那么上面的两个参数就真的10M 25M指的是29532吗? 有人真的研究过吗?我们还是认真研究下explain把。
alias: a Statistics: Num rows: 4744974 Data size: 5863719621 Basic stats: COMPLETE Column stats: PARTIAL
a是大表 numrows和我们的count对的上,但是这个datasize是啥?差不多5.59G了
alias: b Statistics: Num rows: 596 Data size: 328294 Basic stats: COMPLETE Column stats: COMPLETE
b是小表 numrows和我们的count也对的上,这个datasize好像也有点对不上
这里我随便猜猜,怀疑是orc文件自带的压缩,然后解压后的大小?随便说说。反正注意这个数字了!!!
然后来验证。小表开始mapjoin的这个阈值到底是啥?
hive.auto.convert.join.noconditionaltask.size=328293 --小于328294
hive.mapjoin.smalltable.filesize=25000000
采用reduce。
hive.auto.convert.join.noconditionaltask.size=328294 --等于328294
hive.mapjoin.smalltable.filesize=25000000
采用mapjoin,这说明了啥?真正起作用的是explain的参数。
然后我突然有对filesize的25M感兴趣了,这个作用又是啥。
测试结果居然是。。。hive.mapjoin.smalltable.filesize=1 仍然走mapjoin。这时候我不得不怀疑csdn上这么多的文章难道都是抄袭的?
其实我到这里已经有了一个大胆的猜想,对他们都是抄袭的,抄nm哟!!!!
这个参数本身没有错,但是用错了位置!!!因为我已经吃了csdn很多亏了。
注意注意。注意你们用的什么引擎!!!!
都2022年了,大家都是spark tez了。有些b还活在很多年前,还是mr的那一套优化,都过时了老哥。
set hive.execution.engine=mr 来测试这个smallfile.
结果....发现smalltable.filesize卵用没有,如果有用的话请求下博客地址我去学习点赞收藏。
set hive.execution.engine=mr
set hive.mapjoin.smalltable.filesize=1
set hive.auto.convert.join.noconditionaltask.size=20971520
走的是mapjoin 说明啥 这个filesize卵用没有。
set hive.execution.engine=mr
set hive.mapjoin.smalltable.filesize=1
set hive.auto.convert.join.noconditionaltask.size=328294
走的是mapjoin
set hive.auto.convert.join.noconditionaltask.size=328293 --这个小于explain的size
走的是mapjoin
set hive.auto.convert.join.noconditionaltask.size=29532 --原始大小29532
走的mapjoin
set hive.auto.convert.join.noconditionaltask.size=29531 --原始大小29532
走的reduce
说明了啥mr 和spark对这个size的是不一样的。
我们来总结下。
engine=spark的时候,大表关联小表,我们要注意小表explain的大小,而不是实际大小
engine=mr的时候,大表关联小表,我们要注意小表的实际大小也就是hdfs dfs -du 的大小
特别注意 大表关联小表 如果想使用mapjoin 是不能 小表left join 大表的!!!
最后附上nocondtionaltask 哪个解释,我在源码找到这里,感觉会稍微清晰点。maxsize就是。
因能力有限不能完全研读hive源码,这里不能给出明确的答案,但是告诉大家网上的文章很多都有错误,都需要自己实践。
———————————————后续慢慢写,尽量保证测试了发出来———————————
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)