1、提前过滤数据,减少中间数据依赖:
尽量尽早的过滤数据,减少每个阶段的数据量,对于分区表要加分区,同时只选择需要使用到的数据。如下,改写后的写法将会大大减少join的数据量
select ... from A
join B
on A.key = B.key
where A.userid>10
and B.userid<10
and A.dt='20120417'
and B.dt='20120417';
应该改写为:
select .... from (select .... from A
where dt='201200417'
and userid>10
) a
join ( select .... from B
where dt='201200417'
and userid < 10
) b
on a.key = b.key;
2、慎重使用mapjoin,小表注意放在join的左边,否则易导致磁盘及内存的大量消耗
3、避免使用笛卡尔积,笛卡尔积只有1个reduce task,会导致计算超慢,甚至计算不出结果或节点挂掉
如select * from gbk, utf8 where gbk.key= utf8.key and gbk.key > 10;
select * from gbk join utf8 where gbk.key= utf8.key and gbk.key > 10;
上面两种写法就会产生笛卡尔积,可改写为如下形式:
select * from gbk join utf8 on gbk.key= utf8.key where gbk.key > 10;
此外,当多个数据表做连接时,有些童靴喜欢写成以下形式:
tablea join tableb join tablec join ... on tablea.col1 = tableb.col2 and ...
这种形式也会导致笛卡尔积。这种情况可改写为:
tablea join tableb on ( tablea.col1 = tableb.col2 and ... ) join tablec on ... join ... on ...
至于连接条件中有or这种情况,可以考虑使用join + union all或者in等方式来改写。
4、列裁剪(Column Pruning)
在读数据的时候,只读取查询中需要用到的列,而忽略其他列。例如,对于查询:
SELECT a,b FROM T WHERE e < 10;
其中,T 包含 5 个列 (a,b,c,d,e),列 c,d 将会被忽略,只会读取a, b, e 列
这个选项参数默认为真: hive.optimize.cp = true
分区裁剪(Partition Pruning)
在查询的过程中减少不必要的分区。例如,对于下列查询:
SELECT * FROM (SELECT c1, COUNT(1)
FROM T GROUP BY c1) subq
WHERE subq.prtn = 100;
SELECT * FROM T1 JOIN
(SELECT * FROM T2) subq ON (T1.c1=subq.c2)
&nbs