分享

Hive中小表和大表关联查询的疑惑

本帖最后由 javaanddonet 于 2018-4-24 14:45 编辑

网上看到了下面的帖子,感觉写的明白,有大佬给解释一下吗?感激不尽。

>>>>JOIN
例如这样一个查询:INSERTINTO TABLE pv_users
SELECT pv.pageid, u.age
FROM page_view pv JOIN user u ON (pv.userid = u.userid);
3.jpg

把访问和用户表进行关联,生成访问用户表。HiveJoin也是通过MapReduce来完成的。
1.JPG
Map端会分别读入各个表的一部分数据,把这部分数据进行打标,例如pv表标1,user表标2.
2.JPG

Map读取是分布式进行的。标完完后分发到Reduce端,Reduce 端根据Join Key,也就是关联键进行分组。然后按打的标进行排序,也就是图上的Shuffle Sort。
在每一个Reduce分组中,Key为111的在一起,也就是一台机器上。同时,pv表的数据在这台机器的上端,user表的数据在这台机器的下端。--疑问:这里怎么理解这句话?pv表在这台机器的上端?user表在下端?什么意思?

这时候,Reduce把pv表的数据读入到内存里,然后逐条与硬盘上user表的数据做Join就可以了。--疑问:Reduce为什么会把pv表读入到内存,而不会把user表读入内存?哪里可以看出user表是在硬盘上了?

从这个实现可以看出,我们在写HiveJoin的时候,应该尽可能把小表(分布均匀的表)写在左边,大表(或倾斜表)写在右边。这样可以有效利用内存和硬盘的关系,增强Hive的处理能力。--疑问:上面两个表,那个表小呀?一个pv3天记录,一个是user2条记录,我怎么觉得是use表是小表而pv表是大表呢?还有从数据分布均匀的程度来看?我感觉pv没有user表分布的均匀呀?起码user表没有重复的数据。

同时由于使用Join Key进行分发,Hive也只支持等值Join,不支持非等值Join。由于Join和Group By一样存在分发,所以也同样存在着倾斜的问题。所以Join也要对抗倾斜数据,提升查询执行性能。

通常,有一种执行非常快的Join叫MapJoin 。



3.jpg

已有(5)人评论

跳转到指定楼层
desehawk 发表于 2018-4-24 15:51:07

在每一个Reduce分组中,Key为111的在一起,也就是一台机器上。同时,pv表的数据在这台机器的上端,user表的数据在这台机器的下端。--疑问:这里怎么理解这句话?pv表在这台机器的上端?user表在下端?什么意思?
回答:感觉这个应该是说一左一右,左为上,右有下。其实应该是按照图示所说。一上一下。



回复

使用道具 举报

desehawk 发表于 2018-4-24 16:09:39

这时候,Reduce把pv表的数据读入到内存里,然后逐条与硬盘上user表的数据做Join就可以了。--疑问:Reduce为什么会把pv表读入到内存,而不会把user表读入内存?哪里可以看出user表是在硬盘上了?

我们来看:
[mw_shl_code=sql,true]INSERTINTO TABLE pv_users
SELECT pv.pageid, u.age
FROM page_view pv JOIN user u ON (pv.userid = u.userid);[/mw_shl_code]
上面pv表在JOIN 的左边。hive内存加载有一个原则:
hive会将join前面的表数据装载内存,位于join前面的表也就是PV表。
至于user本身其实就在硬盘上。这个其实是一个过程。在reduce时候,我们可能会看到内存的使用会增大,所以这时候我们可以推测到,这时候肯定是读取表到内存了。我们能否看到那,这个恐怕需要一定的技术才能不获取到。


回复

使用道具 举报

desehawk 发表于 2018-4-24 16:14:40

从这个实现可以看出,我们在写HiveJoin的时候,应该尽可能把小表(分布均匀的表)写在左边,大表(或倾斜表)写在右边。这样可以有效利用内存和硬盘的关系,增强Hive的处理能力。--疑问:上面两个表,那个表小呀?一个pv3天记录,一个是user2条记录,我怎么觉得是use表是小表而pv表是大表呢?还有从数据分布均匀的程度来看?我感觉pv没有user表分布的均匀呀?起码user表没有重复的数据。

答:对于这个,由于给出的只是示例数据,我们没法判断那个是小表,那个是大表。其实对于优化hive,将小表放在左边,大表放到join的右边。这样可以提高性能。更准确的说法:把重复关联键少的表放在join前面,做关联可以提高join的效率。


回复

使用道具 举报

javaanddonet 发表于 2018-4-25 13:17:31
desehawk 发表于 2018-4-24 16:14
从这个实现可以看出,我们在写HiveJoin的时候,应该尽可能把小表(分布均匀的表)写在左边,大表(或倾斜 ...

对对对,你说的很对:把重复关联键少的表放在join前面,做关联可以提高join的效率。

网上很多都是是小表放在前面。这种说法不正确。
不过,这句话也有点不好理解。重复关联键 少的表,怎么理解?
首先说:关联健是什么?应该是指的表中用于和另外一张表进行连接查询的字段吧?这个可以是一个列,也可以是多个列吧?
再说:重复?这个怎么理解?是指需要关联列中的值,有重复的吗?
重复关联健:可以理解为表中的需要和另外一张表进行关联的字段的值,不要重复,如果有重复的值在这个列上,尽量少出现重复的数据。对于这样的表,应该放在join的前面?
不知道这么理解对不对。
回复

使用道具 举报

desehawk 发表于 2018-4-29 09:44:54
javaanddonet 发表于 2018-4-25 13:17
对对对,你说的很对:把重复关联键少的表放在join前面,做关联可以提高join的效率。

网上很多都是是小 ...

你的理解对的比如
[mw_shl_code=bash,true]select t1.*,t2.*,t3.* from user_logon_history t1
left join user_logon_history t2 on t1.user_id = t2.user_id and t1.logon_date = t2.logon_date + 1
left join user_logon_history t3 on t2.user_id = t3.user_id and t2.logon_date = t3.logon_date + 1
order by t1.user_id, t1.logon_date;[/mw_shl_code]

其中user_id 就是关联键
重复少比如user_id在小表中都是user_id=1,那么就不要用这个小表了。但是一般来讲,还是小表在前面。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

关闭

推荐上一条 /2 下一条