本文转载自hive性能优化使用group by替代distinct原理-weixin_42412645,感谢作者的知识分享,文章已讲解得非常清晰,笔者不再赘述。
日常业务统计中经常使用除重(distinct)操作,但是当出现某一组数据特别多时就会出现数据倾斜。于是在SQL编写的时候就使用group by来代替distinct,从而让执行效率提升。下面说一下个人的理解。
原始数据page_test表
1 distinct底层原理distinct底层实现原理
select city,count(distinct user_id) from page_test group by city
注意:
- 在map端数据进行过除重操作,这就需要将每个处理过的数据保存起来。
- distinct操作的map端的key为city+user_id(group by列+聚合函数count列)。
- 在数据进行Shuffle的时候分配到reduce的key为(group by列)。
2 group by底层实现原理
select city,user_id from page_test group by city,user_id
注意:
- 在map端数据进行过除重操作,这就需要将每个处理过的数据保存起来。
- map端的key为city+user_id(group by列)并且value为空。
- 在数据进行Shuffle的时候分配到reduce的key为(group by列)。
通过上面的对比我们看出:
- distinct每个reduce处理的数据比group by多。
- distinc整个reduce数比group by少。
- group by基本上没有进行reduce操作,可以直接通过shuffle sort就能得到结果(比如:hadoop二次排序就用到这个原理),同时还可以进行map端的聚合。
根据MapReduce模型的木桶效应可以看出group by效率比distinct要高。同时数据优化一个原则是让分配到reduce的key尽量随机化。可以借鉴HBASE对于key随机化的方法:加盐(随机数+key)