1、多表连接的执行顺序和MapReduce job优化
select
a.ymd
,a.price_close
,b.price_close
,c.price_close
from stocks a join stocks b on a.ymd = b.ymd
join stocks c on a.ymd = c.ymd
where a.symbol = 'APPL' and b.symbol = 'IBM' and c.symbol = 'GE'
大多数情况下Hive会对每对 JOIN 连接对象启动一个MapReduce任务。上例中会首先启动一个MapReduce job对表 a 和表 b 进行连接操作,
然后会启动一个MapReuce job将第一个MapReduce job的输出和表 c 进行连接操作。
当对3个或者更多个表进行 JOIN 连接时,如果每个 ON 子句都使用相同的连接键的话,那么只会产生一个 Map Reduce job。
即Hive通过一个优化可以在同一个Map Reduce job 中连接多个表(需要每个子句中有相同的连接键)。
2、JOIN连接时表的顺序(内连接)
Hive假定查询中最后一个表是最大的那个表,在对每行记录进行连接操作时,它会尝试将其他表缓存起来,然后扫描最后那个表进行计算。
因此用户需要保证连续查询中表的大小从左往右是依次增加的。
用户也可以人为显示告诉查询优化器哪张表是大表,即使它在查询中不是位于最后面的,使用方式如下:
select /*+STREAMTABLE(s)*/s.ymd, s.symbol,s.price_close,d.dividend
from stocks s JOIN dividends d ON s.ymd = d.ymd and s.symbol = d.symbol
where s.symbol='APPL'
3、连接前通过WHERE过滤数据加快查询数据
最直接了当的方式是使用嵌套SELECT语句:
select
s.ymd,s.symbol,s.price_close,d.dividends
from
(
select * from stocks
where symbol = 'AAPL' and exchange = 'NASDAQ'
)s
left outer join
(
select * from dividends
where symbol = 'AAPL' and exchange = 'NASDAQ'
)d
on s.ymd = d.ymd
4、map-side JOIN 优化含有小表的连接
如果所有表中只有一张表是小表,则可以在最大的表通过mapper的时候将小表完全放到内存中。Hive可以在map端执行连接过程(称为mao-side JOIN),这是因为
Hive可以和内存中的小表逐一匹配,从而省略常规连接操作需要的reduce过程。不仅减少了reduce过程,有时也可以同时减少map过程的执行步骤。
set hive.auto.convert.join=true; --让Hive在必要的时候启动优化
hive.mapjoin.smalltable.filesize=25000000; --设置能够使用这个优化的小表的大小(单位是字节)