首先,用我本地的单机版hive建一张测试表,虽然不能模拟大数据量,但是足够说明问题了,准备数据如下:
-- count distinct测试 create table count_distinct_test(id int,name string); insert into count_distinct_test values(1,'a'),(2,'a'),(3,'a'),(4,'b'),(5,'b'),(6,'c'),(7,'d'),(8,'e'),(9,'f'),(10,'g'); explain select count(distinct(name)) from count_distinct_test; explain select count(1) from (select name from count_distinct_test group by name) x;首先,分别执行优化之前的count distinct和group by的语句,观察控制台打印的日志:
count distinct:
可以看到job数为1,整个任务只有1个mr
map输出七条记录,已经进行了去重(减少shuffle数据量,减少io)
group by:
两个job,两个mr
第一个mr的map依然输出7条记录
这块reduce为什么输出0条没有看懂,但是可以想象大数据量情况下,第一个mr会有多个reduce
第二个reduce
map输入是一条纪录,可以想象出第一个mr的reduce的输出就是一个“7”,如果有n个reduce,会输出n个int型,然后第二个mr做的事情就是求和,应该是在reduce中去做
以上执行过程是我的推测,这两个sql执行时间可以忽略,数据量这么小的情况下2个mr比1个mr慢属于正常,大数据量的情况网上也有人做过了,count distinct慢的原因:所有数据都在同一个reduce中计算;而转化sql变成两个mr执行,增大了任务的并行度(具体是怎么算的呢,应该是有一个计数器,每执行一次reduce方法就+1,第一个mr的map逻辑一样,慢应该是慢在reduce端的merge了)
我再粘贴一下两种语句的执行计划:
count distinct
group by: