在使用Impala进行SQL查询的时候,我们经常会使用join来关联多个表进行查询,获取想要的结果。对于表的数量达到千万甚至上亿的时候,不同的join方式所造成的执行速度,可能差距非常大。对于join的实现细节,感兴趣的可以参考:http://hbasefly.com/2017/03/19/sparksql-basic-join/。想直接了解如何加速SQL查询的可以直接跳过这里了。
Impala提供了broadcast和shuffle两种join的方式,那么这两种方式有什么区别呢?可以简单这么理解:
Impala在查询的时候,会根据每个表的统计信息,自动地选择相应的join方式。可以使用以下的SQL语句来给表加上统计信息:
COMPUTE STATS [db_name.]table_name
COMPUTE INCREMENTAL STATS [db_name.]table_name [PARTITION (partition_spec)]
如果用户没有及时地给表进行了统计信息操作或者查询的是kudu表(目前impala无法获取到kudu表的统计信息),那么有可能生成的执行计划就会非常不准确,如下图所示:
上图就是使用了broadcast的join方式,将9000w的数据进行broadcast,与30亿的数据进行join。这样不仅执行比较慢,也会非常消耗内存。此时,我们就可以使用hint来改变SQL的join方式,impala的hint使用非常简单,如下所示:
SELECT STRAIGHT_JOIN select_list FROM
join_left_hand_table
JOIN [{ /* +BROADCAST */ | /* +SHUFFLE */ }]
join_right_hand_table
remainder_of_query;
INSERT insert_clauses
[{ /* +SHUFFLE */ | /* +NOSHUFFLE */ }]
[/* +CLUSTERED */]
SELECT remainder_of_query;
SELECT select_list FROM
table_ref
/* +{SCHEDULE_CACHE_LOCAL | SCHEDULE_DISK_LOCAL | SCHEDULE_REMOTE}
[,RANDOM_REPLICA] */
remainder_of_query;
以上是官方的语法介绍,看起来可能比较晦涩,我们举一个简单的例子进行说明:
select c_custkey,count(o_orderkey)
from customer
join orders
on c_custkey = o_custkey and o_comment not like '%[WORD1]%[WORD2]%'
group by c_custkey
order by c_custkey limit 10;
上面这个SQL我们在测试环境中执行,部分执行计划如下所示:
可以看到,这里默认使用了broadcast的方式,那么如何改变使用shuffle的join方式呢,修改后的SQL如下所示:
select STRAIGHT_JOIN c_custkey,count(o_orderkey)
from customer
join [shuffle] orders
on c_custkey = o_custkey and o_comment not like '%[WORD1]%[WORD2]%'
group by c_custkey
order by c_custkey limit 10;
可以看到,当我们在SQL的相应部分加入了STRAIGHT_JOIN和[shuffle]之后,SQL的执行计划就发生了改变。这里的[shuffle]也可以换成/* +shuffle */,意义是一样的,当然如果我们需要使用broadcast的方式,可以使用[broadcast]或者/* +broadcast */。请注意,有两个地方需要加上hint关键字,select后面加上STRAIGHT_JOIN;join后面加上[shuffle]或者/* +shuffle */。如果是多层嵌套的join方式,也需要在每一层加上STRAIGHT_JOIN和[shuffle]或者/* +shuffle */。外层的hint对于内层的join子语句是不起作用的。如果select后面跟distinct之类的关键字,STRAIGHT_JOIN需要跟在关键字后面。
除了可以改变join的方式之外,impala hint还支持一些其他的功能,这里就不再过多描述,感兴趣的同学可以参考官方文档:https://www.cloudera.com/documentation/enterprise/5-11-x/topics/impala_hints.html。