① Hive的left Join,left Outer Join和left Semi Join三者的区别
以下为两个测试数据表建表语句:
use test;
DROP TABLE IF EXISTS table1;
create table table1(
student_no bigint comment '学号',
student_name string comment '姓名'
)
COMMENT 'test 学生信息'
ROW FORMAT DELIMITED
FIELDS TERMINATED BY '\t'
LINES TERMINATED BY '\n'
STORED AS TEXTFILE;
DROP TABLE IF EXISTS table2;
create table table2(
student_no bigint comment '学号',
class_no bigint comment '课程号'
)
COMMENT 'test 学生选课信息'
ROW FORMAT DELIMITED
FIELDS TERMINATED BY '\t'
LINES TERMINATED BY '\n'
STORED AS TEXTFILE;
load data local inpath 'data_table1.txt' overwrite into table table1;
load data local inpath 'data_table2.txt' overwrite into table table2;
测试数据为:
hive left join测试数据
测试1:left join
语句:
select * from table1 left outer join table2 on(table1.student_no=table2.student_no);
结果:
FAILED: Parse Error: line 1:22 cannot recognize input near ‘left’ ‘join’ ‘table2′ in join type specifier
我用的HIVE版本是0.8,不支持直接的left join写法;
测试2:left outer join
语句:
select * from table1 left outer join table2 on(table1.student_no=table2.student_no);
结果:
1 name1 1 11
1 name1 1 12
1 name1 1 13
2 name2 2 11
2 name2 2 14
3 name3 3 15
3 name3 3 12
4 name4 4 13
4 name4 4 12
5 name5 5 14
5 name5 5 16
6 name6 NULL NULL
可以看到left outer join左边表的数据都列出来了,如果右边表没有对应的列,则写成了NULL值。
同时注意到,如果左边的主键在右边找到了N条,那么结果也是会叉乘得到N条的,比如这里主键为1的显示了右边的3条。
测试3:left semi join
语句:
select * from table1 left semi join table2 on(table1.student_no=table2.student_no);
结果:
1 name1
2 name2
3 name3
4 name4
5 name5
可以看到,只打印出了左边的表中的列,规律是如果主键在右边表中存在,则打印,否则过滤掉了。
结论:
hive不支持’left join’的写法;
hive的left outer join:如果右边有多行和左边表对应,就每一行都映射输出;如果右边没有行与左边行对应,就输出左边行,右边表字段为NULL;
hive的left semi join:相当于sql的in语句,比如上面测试3的语句相当于“select * from table1 where table1.student_no in (table2.student_no)”,注意,结果中是没有B表的字段的。
② sql中left join on 和where的执行顺序
(8)SELECT (9)DISTINCT (11)<Top Num> <select list>
(1)FROM [left_table]
(3)<join_type> JOIN <right_table>
(2)ON <join_condition>
(4)WHERE <where_condition>
(5)GROUP BY <group_by_list>
(6)WITH <CUBE | RollUP>
(7)HAVING <having_condition>
(10)ORDER BY <order_by_list>
逻辑查询处理阶段简介
FROM:对FROM子句中的前两个表执行笛卡尔积(Cartesian proct)(交叉联接),生成虚拟表VT1
ON:对VT1应用ON筛选器。只有那些使<join_condition>为真的行才被插入VT2。
OUTER(JOIN):如 果指定了OUTER JOIN(相对于CROSS JOIN 或(INNER JOIN),保留表(preserved table:左外部联接把左表标记为保留表,右外部联接把右表标记为保留表,完全外部联接把两个表都标记为保留表)中未找到匹配的行将作为外部行添加到 VT2,生成VT3.如果FROM子句包含两个以上的表,则对上一个联接生成的结果表和下一个表重复执行步骤1到步骤3,直到处理完所有的表为止。
WHERE:对VT3应用WHERE筛选器。只有使<where_condition>为true的行才被插入VT4.
GROUP BY:按GROUP BY子句中的列列表对VT4中的行分组,生成VT5.
CUBE|ROLLUP:把超组(Suppergroups)插入VT5,生成VT6.
HAVING:对VT6应用HAVING筛选器。只有使<having_condition>为true的组才会被插入VT7.
SELECT:处理SELECT列表,产生VT8.
DISTINCT:将重复的行从VT8中移除,产生VT9.
ORDER BY:将VT9中的行按ORDER BY 子句中的列列表排序,生成游标(VC10).
TOP:从VC10的开始处选择指定数量或比例的行,生成表VT11,并返回调用者。
③ hive left semi join map是在哪个阶段
hive不支持’left
join’的写法;
hive的left
outer
join:如果右边有多行和左边表对应,就每一行都映射输出;如果右边没有行与左边行对应,就输出左边行,右边表字段为NULL;
hive的left
semi
join:相当于SQL的in语句
以下为两个测试数据表建表语句...
④ Hive的left join,left outer join和left semi join三者的区别
贴一直复制过来的。。
hive不支持‘left
join’的写法(我记得使用的时候好像报错了,最后都改成了outer
join)
hive的left
outer
join:如果右边有多行和左边表对应,就每一行都映射输出;如果右边没有行与左边行对应,就输出左边行,右边表字段为NULL;
hive的left
semi
join:相当于SQL的in语句,比如上面测试3的语句相当于“select
*
from
table1
where
table1.student_no
in
(table2.student_no)”,注意,结果中是没有B表的字段的。
⑤ sql 使用left join后,选取其中两列,进行字段连接,但是出现了null,如何处理多谢!
on 后面跟的是两个表的连接条件,
不匹配时,右表就为NULL
⑥ hive not in 通过什么实现
目前hive不支持 in或not in 中包含查询子句的语法,所以只能通过left join实现。
假设有一个登陆表login(当天登陆记录,只有一个uid),和一个用户注册表regusers(当天注册用户,字段只有一个uid),这两个表都包含一个字段,uid。
in查询
如果要查询当天登陆的注册用户,需要用in查询,hive sql如下:
select login.uid from login left outer join regusers on login.uid=regusers.uid where regusers.uid is not null
如果login表和regusers表按天分区,字段是dt,那么查询2013年1月1号当天登陆的注册用户,hive sql如下:
select login.uid from login day_login left outer join
(select uid from regusers where dt='20130101') day_regusers
on day_login.uid=day_regusers.uid where day_login.dt='20130101' and day_regusers.uid is not null
not in查询
如果要查询当天登陆的老用户(这里假设非当天注册用户就是老用户),需要用not in查询,hive sql如下:
select login.uid from login left outer join regusers on login.uid=regusers.uid where regusers.uid is null;
如果login表和regusers表按天分区,字段是dt,那么查询2013年1月1号当天登陆的老用户,hive sql如下:
select login.uid from login day_login left outer join
(select uid from regusers where dt='20130101') day_regusers
on day_login.uid=day_regusers.uid where day_login.dt='20130101' and day_regusers.uid is null;
Hive join优化
========================================================
由
于 hive 与传统关系型数据库面对的业务场景及底层技术架构都有着很大差异,因此,传统数据库领域的一些技能放到 Hive 中可能已不再适用。关于
hive 的优化与原理、应用的文章,前面也陆陆续续的介绍了一些,但大多都偏向理论层面,本文就介绍一个实例,从实例中一步步加深对 hive
调优的认识与意识。
1、需求
需求我做了简化,很简单,两张表做个 join,求指定城市,每天的 pv,用传统的 RDBMS SQL 写出来就这样的:
?
1
2
3
4
5
6
7
8
9
10
11
SELECT t.statdate,
c.cname,
count(t.cookieid)
FROM tmpdb.city c
JOIN ecdata.ext_trackflow t ON (t.area1= c.cname
OR t.area2 =c.cname
OR t.area3 = c.cname)
WHERE t.statdate>='20140818' and t.statdate<='20140824'
AND platform='pc'
GROUP BY t.statdate,
c.cname;
怎么样?根据 SQL 看懂需求没问题吧?
2、非等值 join 问题
然后把这条 SQL 贴到 hive 中去执行,然后你会发现报错了:
?
1
FAILED: SemanticException [Error 10019]: Line 5:32 OR not supported in JOIN currently 'cname'
这是因为 hive 受限于 MapRece 算法模型,只支持 equi-joins(等值 join),要实现上述的非等值 join,你可以采用笛卡儿积( full Cartesian proct )来实现:
?
1
2
3
4
5
6
7
8
9
10
11
12
13
SELECT t.statdate,
c.cname,
count(t.cookieid)
FROM tmpdb.city c
JOIN ecdata.ext_trackflow t
WHERE t.statdate>='20140818'
AND t.statdate<='20140824'
AND platform='pc'
AND (t.area1= c.cname
OR t.area2 =c.cname
OR t.area3 = c.cname)
GROUP BY t.statdate,
c.cname;
然后再拿着这条语句执行下。
3、优化:rece side join VS Cartesian proct
如果你真的把这条语句放到 Hive 上执行,然后恰好你有张表还非常大,那么恭喜你。。。集群管理员估计会找你的麻烦了。。。
友情提示:笛卡儿积这种语句在 Hive 下慎用,大数据场景下的 m * n 映射结果你懂的。。。对此,Hive 特意提供了一个环境变量:hive.mapred.mode=strict; 防止笛卡儿积的执行:
?
1
FAILED: SemanticException [Error 10052]: In strict mode, cartesian proct is not allowed. If you really want to perform the operation, set hive.mapred.mode=nonstrict
从 2 中的观察得知我们在 on 后面跟 join
条件,走的是 rece side join,如果你在 where 后跟则是走 Cartesian proct,但是这里单条 sql
又没法实现 rece side join,还有没有其它办法呢?
4、改写非等值 join:union all
既然不允许非等值 join,那我们换一下思路,多个子查询 union all,然后汇总:
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
SELECT dt,
name,
count(cid)
FROM
(SELECT t.statdate dt,
c.cname name,
t.cookieid cid
FROM tmpdb.city c
JOIN ecdata.ext_trackflow t ON t.area1 =c.cname
WHERE t.statdate>='20140818'
AND t.statdate<='20140824'
AND platform='pc'
UNION ALL SELECT t.statdate dt,
c.cname name,
t.cookieid cid
FROM tmpdb.city c
JOIN ecdata.ext_trackflow t ON t.area2 =c.cname
WHERE t.statdate>='20140818'
AND t.statdate<='20140824'
AND platform='pc'
UNION ALL SELECT t.statdate dt,
c.cname name,
t.cookieid cid
FROM tmpdb.city c
JOIN ecdata.ext_trackflow t ON t.area3 =c.cname
WHERE t.statdate>='20140818'
AND t.statdate<='20140824'
AND platform='pc') tmp_trackflow
GROUP BY dt,
name;
5、优化:map side join
上述语句走的是 rece side join,从我们的需求及业务得知,tmpdb.city 是一张字典表,数据量很小,因此我们可以试试把上述的语句改写成 mapjoin:
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
SELECT dt,
name,
count(cid)
FROM
(SELECT /*+ MAPJOIN(c) */ t.statdate dt,
c.cname name,
t.cookieid cid
FROM tmpdb.city c
JOIN ecdata.ext_trackflow t ON t.area1 =c.cname
WHERE t.statdate>='20140818'
AND t.statdate<='20140824'
AND platform='pc'
UNION ALL SELECT /*+ MAPJOIN(c) */ t.statdate dt,
c.cname name,
t.cookieid cid
FROM tmpdb.city c
JOIN ecdata.ext_trackflow t ON t.area2 =c.cname
WHERE t.statdate>='20140818'
AND t.statdate<='20140824'
AND platform='pc'
UNION ALL SELECT /*+ MAPJOIN(c) */ t.statdate dt,
c.cname name,
t.cookieid cid
FROM tmpdb.city c
JOIN ecdata.ext_trackflow t ON t.area3 =c.cname
WHERE t.statdate>='20140818'
AND t.statdate<='20140824'
AND platform='pc') tmp_trackflow
GROUP BY dt,
name;
6、优化无极限:开启 parallel 和 控制 rece 个数
上述语句执行时,你可以看到执行计划和状态信息,以及结合你的 union all 语句可知,三个 union 语句之间没有依赖关系,其实是可以并行执行的:
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
explain SQL...
...
STAGE DEPENDENCIES:
Stage-11 is a root stage
Stage-1 depends on stages: Stage-11
Stage-2 depends on stages: Stage-1
Stage-3 depends on stages: Stage-2, Stage-6, Stage-9
Stage-12 is a root stage
Stage-5 depends on stages: Stage-12
Stage-6 depends on stages: Stage-5
Stage-13 is a root stage
Stage-8 depends on stages: Stage-13
Stage-9 depends on stages: Stage-8
Stage-0 is a root stage
...
我们在 SQL 前加上如下环境变量选项:
?
1
2
set mapred.rece.tasks=60;
set hive.exec.parallel=true;
让执行计划中的 Stage-11、Stage-12、Stage-13 并行执行,并控制好 rece task 个数。
完整的语句如下:
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
hive -e "
SET mapred.rece.tasks=60;
SET hive.exec.parallel=TRUE;
SELECT dt,
name,
count(cid)
FROM
(SELECT /*+ MAPJOIN(c) */ t.statdate dt,
c.cname name,
t.cookieid cid
FROM tmpdb.city c
JOIN ecdata.ext_trackflow t ON t.area1 =c.cname
WHERE t.statdate>='20140818'
AND t.statdate<='20140824'
AND platform='pc'
UNION ALL SELECT /*+ MAPJOIN(c) */ t.statdate dt,
c.cname name,
t.cookieid cid
FROM tmpdb.city c
JOIN ecdata.ext_trackflow t ON t.area2 =c.cname
WHERE t.statdate>='20140818'
AND t.statdate<='20140824'
AND platform='pc'
UNION ALL SELECT /*+ MAPJOIN(c) */ t.statdate dt,
c.cname name,
t.cookieid cid
FROM tmpdb.city c
JOIN ecdata.ext_trackflow t ON t.area3 =c.cname
WHERE t.statdate>='20140818'
AND t.statdate<='20140824'
AND platform='pc') tmp_trackflow
GROUP BY dt,
name;
" > a1.txt
最后的优化效果是:2 中的语句三个小时没出结果。。。5 比 4 快 8 倍左右,6 比 5 快 2 倍左右,最终 10min 出结果。
⑦ Hive的left join,left outer join和left semi join三者的区别
贴一直复制过来的。。hive不支持‘left join’的写法(我记得使用的时候好像报错了,最后都改成了outer join)hive的left outer join:如果右边有多行和左边表对应,就每一行都映射输出;如果右边没有行与左边行对应,就输出左边行,右边表字段为NULL;hive的left semi join:相当于SQL的in语句,比如上面测试3的语句相当于“select * from table1 where table1.student_no in (table2.student_no)”,注意,结果中是没有B表的字段的。
⑧ Hive的left join,left outer join和left semi join三者的区别
hive不支持’left join’的写法; hive的left outer join:如果右边有多行和左边表对应,就每一行都映射输出;如果右边没有行与左边行对应,就虎虎港臼蕃铰歌歇攻忙输出左边行,右边表字段为NULL; hive的left semi join:相当于SQL的in语句 以下为两个测试数据表建表语句...
⑨ Hive的left join,left outer join和left semi join三者的区别
Hive是基于Hadoop的一个数据仓库工具,可以将结构化的数据文件映射为一张数据库表,并提供简单的sql查询功能,可以将sql语句转换为MapRece任务进行运行。
最常用的就是多表关联查询,主要讲解下join、outer join和semi join的具体使用。
join是最简单的关联操作,两边关联只取交集。Hive没有left 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.valueFROM aWHERE a.key in (SELECT b.key FROM B);可以改写为:SELECT a.key, a.valueFROM a LEFT OUTER JOIN b ON (a.key = b.key)WHERE b.key <> NULL;一个更高效的实现为:SELECT a.key, a.valueFROM a LEFT SEMI JOIN b on (a.key = b.key);
left semi join是0.5.0以上版本的特性。
⑩ hive中mapjoin和普通join的区别
hive支持’left join’写; hiveleft outer join:右边行左边表应,每行都映射输;右边没行与左边行应,输左边行,右边表字段NULL; hiveleft semi join:相于SQLin语句 两测试数据表建表语句...