Hive的left join,left outer join 用法和left semi join三者的区别

声明:现大部分文章为寻找问题时在网上相互转载,在此博客中做个记录,方便自己也方便有类似问题的朋友,故原出处已不好查到,如有侵权,请发邮件表明文章和原出处地址,我一定在文章中注明。谢谢。
业务思维、结果导向、成本意识
随笔- 467&
&&&&&&&&&&&
hive& select * from zz0; 111111 222222 888888 hive& select * from zz1; 111111 333333 444444 888888
hive& select * from zz0 join zz1 on zz0.uid = zz1. 1111 8888 hive& select * from zz0 left outer join zz1 on zz0.uid = zz1. 1111 222222& NULL 8888 hive& select * from zz0 right outer join zz1 on zz0.uid = zz1. NULL 1111 NULL&&& 333333 NULL&&& 444444 8888 hive& select * from zz0 full outer join zz1 on zz0.uid = zz1. NULL 1111 222222& NULL NULL&&& 333333 NULL&&& 444444 8888 hive& select * from zz0 left semi join zz1 on zz0.uid = zz1. 1111 8888
写好Hive 程序的五个提示
使用Hive可以高效而又快速地编写复杂的MapReduce查询逻辑。但是某些情况下,因为不熟悉数据特性,或没有遵循Hive的优化约定,Hive计算任务会变得非常低效,甚至无法得到结果。一个&好&的Hive程序仍然需要对Hive运行机制有深入的了解。
有一些大家比较熟悉的优化约定包括:Join中需要将大表写在靠右的位置;尽量使用UDF而不是transfrom&&诸如此类。下面讨论5个性能和逻辑相关的问题,帮助你写出更好的Hive程序。
Hive的排序关键字是SORT BY,它有意区别于传统数据库的ORDER BY也是为了强调两者的区别&SORT BY只能在单机范围内排序。考虑以下表定义:
CREATE TABLE if not exists t_order(
id int, -- 订单编号
sale_id int, -- 销售ID
customer_id int, -- 客户ID
product _id int, -- 产品ID
amount int -- 数量
) PARTITIONED BY (ds STRING);
在表中查询所有销售记录,并按照销售ID和数量排序:
set mapred.reduce.tasks=2;
Select sale_id, amount from t_order
Sort by sale_id,
这一查询可能得到非期望的排序。指定的2个reducer分发到的数据可能是(各自排序):
Reducer1:
Sale_id | amount
Reducer2:
Sale_id | amount
因为上述查询没有reduce key,hive会生成随机数作为reduce key。这样的话输入记录也随机地被分发到不同reducer机器上去了。为了保证reducer之间没有重复的sale_id记录,可以使用DISTRIBUTE BY关键字指定分发key为sale_id。改造后的HQL如下:
set mapred.reduce.tasks=2;
Select sale_id, amount from t_order
Distribute by sale_id
Sort by sale_id,
这样能够保证查询的销售记录集合中,销售ID对应的数量是正确排序的,但是销售ID不能正确排序,原因是hive使用hadoop默认的HashPartitioner分发数据。
这就涉及到一个全排序的问题。解决的办法无外乎两种:
1.) 不分发数据,使用单个reducer:
set mapred.reduce.tasks=1;
这一方法的缺陷在于reduce端成为了性能瓶颈,而且在数据量大的情况下一般都无法得到结果。但是实践中这仍然是最常用的方法,原因是通常排序的查询是为了得到排名靠前的若干结果,因此可以用limit子句大大减少数据量。使用limit n后,传输到reduce端(单机)的数据记录数就减少到n* (map个数)。
2.) 修改Partitioner,这种方法可以做到全排序。这里可以使用Hadoop自带的TotalOrderPartitioner(来自于Yahoo!的TeraSort项目),这是一个为了支持跨reducer分发有序数据开发的Partitioner,它需要一个SequenceFile格式的文件指定分发的数据区间。如果我们已经生成了这一文件(存储在/tmp/range_key_list,分成100个reducer),可以将上述查询改写为
set mapred.reduce.tasks=100;
set hive.mapred.partitioner=org.apache.hadoop.mapred.lib.TotalOrderP
set total.order.partitioner.path=/tmp/ range_key_
Select sale_id, amount from t_order
Cluster by sale_id
有很多种方法生成这一区间文件(例如hadoop自带的o.a.h.mapreduce.lib.partition.InputSampler工具)。这里介绍用Hive生成的方法,例如有一个按id有序的t_sale表:
CREATE TABLE if not exists t_sale (
name string,
loc string
则生成按sale_id分发的区间文件的方法是:
create external table range_keys(sale_id int)
row format serde
'org.apache.hadoop.hive.serde2.binarysortable.BinarySortableSerDe'
inputformat
'org.apache.hadoop.mapred.TextInputFormat'
outputformat
'org.apache.hadoop.hive.ql.io.HiveNullValueSequenceFileOutputFormat'
location '/tmp/range_key_list';
insert overwrite table range_keys
select distinct sale_id
from source t_sale sampletable(BUCKET 100 OUT OF 100 ON rand()) s
sort by sale_
生成的文件(/tmp/range_key_list目录下)可以让TotalOrderPartitioner按sale_id有序地分发reduce处理的数据。区间文件需要考虑的主要问题是数据分发的均衡性,这有赖于对数据深入的理解。
怎样做笛卡尔积?
当Hive设定为严格模式(hive.mapred.mode=strict)时,不允许在HQL语句中出现笛卡尔积,这实际说明了Hive对笛卡尔积支持较弱。因为找不到Join key,Hive只能使用1个reducer来完成笛卡尔积。
当然也可以用上面说的limit的办法来减少某个表参与join的数据量,但对于需要笛卡尔积语义的需求来说,经常是一个大表和一个小表的Join操作,结果仍然很大(以至于无法用单机处理),这时MapJoin才是最好的解决办法。
MapJoin,顾名思义,会在Map端完成Join操作。这需要将Join操作的一个或多个表完全读入内存。
MapJoin的用法是在查询/子查询的SELECT关键字后面添加/*+ MAPJOIN(tablelist) */提示优化器转化为MapJoin(目前Hive的优化器不能自动优化MapJoin)。其中tablelist可以是一个表,或以逗号连接的表的列表。tablelist中的表将会读入内存,应该将小表写在这里。
PS:有用户说MapJoin在子查询中可能出现未知BUG。在大表和小表做笛卡尔积时,规避笛卡尔积的方法是,给Join添加一个Join key,原理很简单:将小表扩充一列join key,并将小表的条目复制数倍,join key各不相同;将大表扩充一列join key为随机数。
怎样写exist in子句?
Hive不支持where子句中的子查询,SQL常用的exist in子句需要改写。这一改写相对简单。考虑以下SQL查询语句:
SELECT a.key, a.value
WHERE a.key in
(SELECT b.key
可以改写为
SELECT a.key, a.value
FROM a LEFT OUTER JOIN b ON (a.key = b.key)
WHERE b.key && NULL;
一个更高效的实现是利用left semi join改写为:
SELECT a.key, a.val
FROM a LEFT SEMI JOIN b on (a.key = b.key);
left semi join是0.5.0以上版本的特性。
Hive怎样决定reducer个数?
Hadoop MapReduce程序中,reducer个数的设定极大影响执行效率,这使得Hive怎样决定reducer个数成为一个关键问题。遗憾的是Hive的估计机制很弱,不指定reducer个数的情况下,Hive会猜测确定一个reducer个数,基于以下两个设定:
1. hive.exec.reducers.bytes.per.reducer(默认为1000^3)
2. hive.exec.reducers.max(默认为999)
计算reducer数的公式很简单:
N=min(参数2,总输入数据量/参数1)
通常情况下,有必要手动指定reducer个数。考虑到map阶段的输出数据量通常会比输入有大幅减少,因此即使不设定reducer个数,重设参数2还是必要的。依据Hadoop的经验,可以将参数2设定为0.95*(集群中TaskTracker个数)。
合并MapReduce操作
Multi-group by
Multi-group by是Hive的一个非常好的特性,它使得Hive中利用中间结果变得非常方便。例如,
FROM (SELECT a.status, b.school, b.gender
FROM status_updates a JOIN profiles b
ON (a.userid = b.userid and
INSERT OVERWRITE TABLE gender_summary
PARTITION(ds='')
SELECT subq1.gender, COUNT(1) GROUP BY subq1.gender
INSERT OVERWRITE TABLE school_summary
PARTITION(ds='')
SELECT subq1.school, COUNT(1) GROUP BY subq1.school
上述查询语句使用了Multi-group by特性连续group by了2次数据,使用不同的group by key。这一特性可以减少一次MapReduce操作。
Multi-distinct
Multi-distinct是淘宝开发的另一个multi-xxx特性,使用Multi-distinct可以在同一查询/子查询中使用多个distinct,这同样减少了多次MapReduce操作。
阅读(...) 评论()
声明:现大部分文章为寻找问题时在网上相互转载,在此博客中做个记录,方便自己也方便有类似问题的朋友,故原出处已不好查到,如有侵权,请发邮件表明文章和原出处地址,我一定在文章中注明。谢谢。left outer join和left join有区别?_百度知道
色情、暴力
我们会通过消息、邮箱等方式尽快将举报结果通知您。
left outer join和left join有区别?
我有更好的答案
bleft join 是 left outer join
简写以下是例子a表.f1 = b.f4
6 select a.* .* from a a left outer join b b on a
采纳率:32%
没区别,left [outer ]join都实现的是关键字会从左表那里返回所有的行,即使在右表中没有匹配的行。
left outer join 常简写为left join
为您推荐:
其他类似问题
join的相关知识
等待您来回答hive中left join 和 join的问题
什么时候用join,什么时候用left join?我总是弄不清楚,求大神指点~~~
虽然不知道什么是hive, 但在mysql当中,查询 字段 左表 join 右表 on 条件,只会查询出左表和右表连接相对应的字段,其他字段不会显示,如果是查询 字段 左表 left join 右表 on 条件,左表所有的字段都会显示,即便在右表中没有相对应的字段。举例的话,左表十个人有三个人买了商品,右表有相对应的三个人买的商品,在查询的时候如果用join只能查出买商品的三个人其他七个人不会查出来,如果是left join除了查出买商品的三个人和对应的商品外,左表剩下七个人的要查询的个人信息也会被输出,那七个人对应得购买商品的记录为null,作用就是能知道十个人中谁没买东西。
你还没有登录,请先登录或注册慕课网帐号
left join(左联接) 返回包括左表中的所有记录和右表中联结字段相等的记录 right join(右联接) 返回包括右表中的所有记录和左表中联结字段相等的记录inner join(等值连接) 只返回两个表中联结字段相等的行
你还没有登录,请先登录或注册慕课网帐号
9572人关注
Copyright (C)
All Rights Reserved | 京ICP备 号-28349人阅读
分布式(8)
Java(37)
Hive是基于Hadoop的一个数据仓库工具,可以将结构化的数据文件映射为一张数据库表,并提供简单的sql查询功能,可以将sql语句转换为MapReduce任务进行运行。
最常用的就是多表关联查询,主要讲解下join、outer join和semi join的具体使用。
join是最简单的关联操作,两边关联只取交集。
outer join分为left outer join、right outer join和full outer join。
left outer join是以左表驱动,右表不存在的key均赋值为null;
right outer join是以右表驱动,左表不存在的key均赋值为null;
full outer join全表关联,将两表完整的进行笛卡尔积操作,左右表均可赋值为null。
semi join最主要的使用场景就是解决exist in。
Hive不支持where子句中的子查询,SQL常用的exist in子句在Hive中是不支持的。
SELECT a.key, a.value
WHERE a.key in (SELECT b.key FROM B);
可以改写为:
SELECT a.key, a.value
FROM a LEFT OUTER JOIN b ON (a.key = b.key)
WHERE b.key && NULL;
一个更高效的实现为:
SELECT a.key, a.value
FROM a LEFT SEMI JOIN b on (a.key = b.key);
left semi join是0.5.0以上版本的特性。
&&相关文章推荐
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:158709次
积分:1710
积分:1710
排名:千里之外
原创:41篇
评论:19条
(1)(1)(3)(1)(3)(2)(3)(1)(1)(16)(12)(4)
(window.slotbydup = window.slotbydup || []).push({
id: '4740881',
container: s,
size: '200,200',
display: 'inlay-fix'hive中的LEFT&SEMI&JOIN
LEFT SEMI JOIN 是 IN/EXISTS 子查询的一种更高效的实现。
Hive 当前没有实现 IN/EXISTS 子查询,所以你可以用 LEFT SEMI JOIN
重写你的子查询语句。LEFT SEMI JOIN 的限制是, JOIN
子句中右边的表只能在&
ON 子句中设置过滤条件,在 WHERE 子句、SELECT 子句或其他地方过滤都不行。
& SELECT a.key, a.value
& WHERE a.key in
& &(SELECT b.key
& & FROM B);
可以被重写为:
& &SELECT a.key, a.val
& &FROM a LEFT SEMI JOIN b on
(a.key = b.key)
已投稿到:
以上网友发言只代表其个人观点,不代表新浪网的观点或立场。

我要回帖

更多关于 spark leftouterjoin 的文章

 

随机推荐