酷的像风,野的像狗❤️
不谈亏欠,只谢相遇❤️

让人最安心的还是学生时代
吃饱饭后
拿着一杯冰镇的果汁走着
看傍晚的晚霞
和你
🌈🌈🌈
这次的话题是
hive优化之小表和大表的关联
先养眼,再看题
❤️
今天还是小姐姐


Hive优化
Hive的优化多种多样,从处理前到处理后及中间的参数都是可以调整。
但这次,换个新鲜且大胆的优化方案:小表和大表的关联。
[toc]
1. 结论
2. 分析
3. demo
4. 总结



结论
众所周知,在数据库的优化中,有个优化是小表在左,大表在右,因为小表可以先放到内存中,然后大表的每条记录再去内存中进行检测,最终完成关联查询。
但在hive中,可不一定合理。
> 首先,分析hive是怎么运行sql的。
在hive中,不管多么复杂的sql终究会转换为mr的job去执行。

在此先回顾mr的shuffle:map阶段在环形缓冲区写入磁盘的时候,会默认为100M的临时文件,并在写入到reduce之前会将这些临时文件合并成一个文件,即最终每个reduce都只处理一个文件
但是在mr中,不管是怎么的逻辑,都离不开写磁盘和读内容这个过程,因此小表在左,大表在右是不合理的。
小声逼逼:毕竟数据库的执行方式和hive的执行方式是不同的
so,正确的说法:把重复关联键少的表在左,可以提升效率
so,我们分析hive对两表的关联在底层是如何实现的


关联键和标记是在join左边还是右边的标识作为组合键(key),把一条记录以及标记是在join左边还是右边合起来作为值(value)。
在reduce的shuffle阶段,按照组合键的关联键进行主排序,当关联键相同时,再按照标示位进行辅助排序。
而在分区段中,只用关联键进行分区段,这样关联键相同的记录就会在同一个value list中,同时保证了join左边的表记录在value list的前面,而join右边的表的记录在value list的右边。


举个🌰
A join B on (A.id = B.id)
如果:A表有2条,B表有5条,A左B右
那么最终reduce产生的结果是 key=3,value list = [A表中id为3的记录,B表中id为3的记录]
1. reduce先读第一条记录v[0],如果v[0]是A表的记录,用了1次读取操作;
2. v[1]仍是A表的记录,就算2次读取操作;
3. v[2]是B表的记录,此时v[0]与v[2]可以直接关联输出,累计用了3次操作。
4. v[0]与v[3]~v[6]进行关联输出,累计用了7次操作;
5. v[1]与v[3]~v[6]进行关联输出,累计用了12次操作。
画图展示下:
<3,[1,1,1,1,1,1,1]>key为3value前2个1为A表,后5个1为B表v[0] -> 1v[1] -> 2v[0],v[2] -> 3v[0],v[3] -> 4v[0],v[4] -> 5v[0],v[5] -> 6v[0],v[6] -> 7v[1],v[2] -> 8v[1],v[3] -> 9v[1],v[4] -> 10v[1],v[5] -> 11v[1],v[6] -> 12

如果:A表有5条,B表有2条,A左B右
1. reduce在读取时,v[0]是A表数据,用了1次读取操作;
2. v[1]也是A表数据,用了2次读取操作;
3. v[2],v[3],v[4]都是A表数据,用了5次读取操作;
4. v[5]是B表数据,此时v[0]和v[5]可以直接关联输出,累计6次读取操作
5. v[0]和v[6]进行关联输出,累计7次读取操作
6. v[1]和v[5]、v[6];
v[2]和v[5]、v[6];
v[3]和v[5]、v[6];
v[4]和v[5]、v[6];进行关联查询,累计15次操作
画图展示下:
<3,[1,1,1,1,1,1,1]>key为3value前5个1为A表,后2个1为B表v[0] -> 1v[1] -> 2v[2] -> 3v[3] -> 4v[4] -> 5v[0],v[5] -> 6v[0],v[6] -> 7v[1],v[5] -> 8v[1],v[6] -> 9v[2],v[5] -> 10v[2],v[6] -> 11v[3],v[5] -> 12v[3],v[6] -> 13v[4],v[5] -> 14v[4],v[6] -> 15


最终结论
写在关联左侧的表每有1条重复的关联键时,底层就会多一次运算处理
假设A表有一千万个id,平均每个id有3条重复数据,那么把A表放在前面做关联就会多做三千万次的运算处理。



郭大熊的公众号
个人博客 : www.guodaxiong.com
如果不曾见过阳光,我本可以忍受黑暗
Hi GuoDaXiong
我是狗子
祝你幸福






