Hive优化实践
1. 离线数据处理的主要挑战: 数据倾斜
-
"倾斜"指统计学历的偏态分布;
-
所谓偏态分布, 即统计数据峰值与平均值不相等的频率分布
-
根据峰值小于或大于平均值可分为正偏函数和负偏函数,其偏离的程度可用偏态系数刻画;
-
Hive的优化正是采用各种措施和方法对上述场景的倾斜问题进行优化和处理
2. Hive使用方面的优化
- 对于大众的, KPI相关的指标等通常设计良好的数据仓库公共层肯定已经包含了,直接使用即可,不需要自行汇总
- 扫描的范围尽量缩小,节省计算和存储资源
- 尽量不要使用*,要查哪列就指定哪些列
- 输入文件不要是大量的小文件;Hive的默认Input Split是128MB,小文件可以先合并成大文件;
- 使用Hive优化技术
3. join无关的优化
3.1 group by引起的倾斜优化
-
主要是输入数据行按照group by列分布不均匀引起的;
-
比如按照供应商对销售明细事实表来统计订单数,那么部分大供应商的订单量显然非常多,而多数的订单量就一般
-
由于group by的时候是按照供应商的ID分发到每个Reduce Task,那么此时分配到大供应商的Reduce Task就分配了更多的订单,从而导致数据倾斜
-
对于group by的优化措施
--是否在Map端进行聚合,默认为true set hive.map.aggr = true; -- 有数据倾斜的时候进行负载均衡,默认是false set hive.groupby.skewindata = true; --还可以设置Map端进行聚合操作的条目数目 set hive.groupby.mapaggr.checkinterval=100000;
- 此时Hive在数据倾斜的时候会进行负载均衡,生成的查询集合会有两个MapReduce Job;
- 第一MapReduce Job中,Map的输出结果集合会随机分布到Reduce中,每个Reduce做部分聚合操作并输出结果,这样处理的结果是相同的GroupBy Key有可能被分布到不同的Reduce中,从而达到负载均衡的目的;
- 第二个MapReduce Job再根据预处理的数据结果按照GroupBy Key分布到Reduce中(这过程可以保证相同的GroupBy Key被分布到同一个Reduce中),最后完成最终的聚合操作
- 此时Hive在数据倾斜的时候会进行负载均衡,生成的查询集合会有两个MapReduce Job;
-
3.2 count distinct优化
-
count distinct需要小心使用,很容易引发性能问题,如下
select count(distinct user) from some_table
-
由于必须去重,因此Hive将会把Map阶段的输出全部分布到一个Reduce Task上,很容易引起性能问题,可以这样优化
select count(*) from ( select user from some_table group by user ) tmp; --原理为:先利用group by去重,再统计group by的行数目;
-
4. 大表join小表优化
-
大表join小表优化案例
-
假如供应商会进行评级,比如(五到一星), 此时业务人员希望能够分析各供应商星级的每天销售情况及其占比;
-
现实世界的 八准则将导致订单集中在部分供应商上,而好的供应 商的评级通常会更高,此时更加剧了数据倾斜的程度,如果不加以优化, SQL 将会耗 费很长时间,甚至运行不出结果
-
select Seller_srar, count(order_id) as ordre_cnt from ( select order_id,seller_id from dwd_sls_fact_detail_table where partition_value ='20170101' ) a Left outer join( select seller_id,seller_star from dim_seller where partition_value='20170101' ) b on a.seller_id = b.seller_id group by b.seller_star;
-
添加mapjoin hint优化sql
select /*+mapjoin(b)*/ Seller_srar, count(order_id) as ordre_cnt from ( select order_id,seller_id from dwd_sls_fact_detail_table where partition_value ='20170101' ) a Left outer join( select seller_id,seller_star from dim_seller where partition_value='20170101' ) b on
-
-