目录

一、一个实际场景,组合多的问题

1、场景描述

2、如何优化?

二、Hive中的排序

1、order by (全局排序)

2、sort by (分区内排序)

3、distribute  by  (分区排序)

4、cluster  by  (简写)

5、一个关于排序的实际场景例子

(1)问题描述

(2)解决方法

三、hive中的join

1、普通的join(left,inner等)(common/shuffle/reduce  join)

2、map  join   大小表关联

3、SMB join    大表关联大表

四、hive的参数优化

1、combine的参数

(1)combine 在map端聚合

(2)在map端进行聚合的条数

2、负载均衡

(1)数据倾斜的时候

五、思考题

1、分桶表

(1)概念

(2)创建一个分桶表

(3)查看分桶表内

(4)查看HDFS

 (5)分桶表常用在抽样查询

(6)实现 SMB  join

2、Count(Distinct) 去重统计

3、行列过滤

4、避免笛卡尔积


一、一个实际场景,组合多的问题

1、场景描述

-- a ,b,c等字段是用户的标签

select a , b ,c ......

count(distinct user_id)

from table_a ----数据大约10亿条

group by ds

,cube(a,b,c,d,e,f,g) --- 128种组合

,grouping sets(

x ,y ,z , ()

) --- 4 种组合

可能最后结果只有几百条

2、如何优化?

找分析师,聊清楚具体想要哪些组合的统计

不要把精力都钻到 SQL上 !!要了解相应的业务

二、Hive中的排序

1、order by (全局排序)

select * from emp order by sal ;

只有一个 reduce ,这里无论设置多少个reduce,都是一个

优点:全局排序

缺点:当数据量大的时候,耗时长,效率低,适用于数据量小的场景

2、sort by (分区内排序)

对每一个reduce内部数据进行排序,全局结果来说不是排序的

适用于数据量大,但是对排序要求不严格的场景,可以大幅提高执行效率

需要预先设定reduce个数,reduce结果文件内部有序

set  mapreduce.job.reduces = 10 ;

select *  from   emp sort by sal  desc;

3、distribute  by  (分区排序)

控制特定的key 到指定的reducer,方便后续的聚合操作,类似于MR中自定义分区,一般结合sort by 使用

需要预先设定reduce个数,否则不会启动相应的reducer进行任务的执行,导致最后不能完全分区。

set  mapreduce.job.reduces = 10 ;

select *  from   emp distribute by deptno sort by sal  desc;

注意

 (1)distribute by  要在sort by之前

 (2) distribute  by  的分区规则是根据分区字段 hash 码与 reduce的个数进行取模后,余数相同的分到一个分区

4、cluster  by  (简写)

当distribute by 和 sort by 的字段相同时,可以简写成 cluster by ,但是这个排序只能升序

select *  from   emp distribute by deptno sort by deptno ;

select *  from  emp cluster by deptno;

5、一个关于排序的实际场景例子

(1)问题描述

订单表,取GMV(商品交易总额)top前100的用户

假如有  1 亿用户   有GMV

(2)解决方法

多个reduce排序,每个分区排序取前100,最后汇总再全局排序,取前100

select
    *
from 
(
    select 
        user_id
        ,gmv
    from  dwd_order_df
    distribute by city sort by gmv desc limit 100
) x

order by  gmv  desc limit 100 ;

三、hive中的join

1、普通的join(left,inner等)(common/shuffle/reduce  join)

 最普通的join,会产生shuffer,且这个会在reduce端做join

2、map  join   大小表关联

小表的阈值控制   

set  hive.mapjoin.smalltable.filesize = 25123456 ;    --  大约25M

(1)写法

select 
    /*+MAPJOIN(b)*/count(1)
from a  -- 大表
join b  -- 小表
on a.id = b.id

流程:可以将b表放在内存,在map端做join ,这个join就发生在map操作的时候,每当扫描一个大表的数据,就要去内存查看小表,有没有与之相等的,继而进行关联。

map端的join优势:没有shuffle 

(2)另一种写法 加上参数

set hive.auto.convert.join = true ;
select 
    count(1)
from a  -- 大表
join b  -- 小表
on a.id = b.id

3、SMB join    大表关联大表

SMB  --》sort  merge  bucket

有  a表  5 亿    , b表 10亿

使用限制

(1)a  b  必须都是分桶的

(2)a b分桶的key必须是关联条件即是key join

(3)设置一些参数

set hive.auto.convert.sortmerge.join = true
set hive.optimize.bucketmapjoin = true;
set hive.optimize.bucketmapjoin.sortedmerge = true;

(4)语句执行

select 
    count(1)
from a  -- 大表
join b  -- 小表
on a.id = b.id

四、hive的参数优化

1、combine的参数

(1)combine 在map端聚合

set hive .map.aggr   = true

(2)在map端进行聚合的条数

set  hive.groupby.mapaggr.checkinterval = 100000;  --默认10万

2、负载均衡

(1)数据倾斜的时候

set  hive.groupby.skewindata = true

当选定为TRUE时,生成的查询计划会产生两个 MR  job

先加随机前缀,聚合一次,再去掉随机前缀,再聚合一次

五、思考题

1、分桶表

(1)概念

分区针对的是数据的存储路径;分桶针对的是数据文件。

(2)创建一个分桶表

准备数据

           student.txt

1001	ss1
1002	ss2
1003	ss3
1004	ss4
1005	ss5
1006	ss6
1007	ss7
1008	ss8
1009	ss9
1010	ss10
1011	ss11
1012	ss12
1013	ss13
1014	ss14
1015	ss15
1016	ss16

创建分桶表

create table stu_buck(id int, name string)
clustered by(id) 
into 4 buckets
row format delimited fields terminated by '\t';

导入数据

load data local inpath '/home/peizk/student.txt' into table stu_buck;

(3)查看分桶表内

hiveleft join和join的效率_hive

(4)查看HDFS

hiveleft join和join的效率_hadoop_02

 (5)分桶表常用在抽样查询

查询表stu_buck中的数据。

select * from stu_buck tablesample(bucket 1 out of 4 on id);

注:tablesample是抽样语句,语法:TABLESAMPLE(BUCKET x OUT OF y) 。

y必须是table总bucket数的倍数或者因子。hive根据y的大小,决定抽样的比例。例如,table总共分了4份,当y=2时,抽取(4/2=)2个bucket的数据,当y=8时,抽取(4/8=)1/2个bucket的数据。

x表示从哪个bucket开始抽取,如果需要取多个桶,以后的桶号为当前桶号加上y。例如,table总bucket数为4,tablesample(bucket 1 out of 2),表示总共抽取(4/2=)2个bucket的数据,抽取第1(x)个和第3(x+y)个bucket的数据。

注意:x的值必须小于等于y的值,否则

FAILED: SemanticException [Error 10061]: Numerator should not be bigger than denominator in sample clause for table stu_buck

(6)实现 SMB  join

在创建一个stu_buck2表数据同stu_buck

create table stu_buck2(id int, name string)
clustered by(id) 
into 4 buckets
row format delimited fields terminated by '\t';

load data local inpath '/home/peizk/student.txt' into table stu_buck2;

 实现  SMB join

set hive.auto.convert.sortmerge.join=true;
set hive.optimize.bucketmapjoin=true;
set hive.optimize.bucketmapjoin.sortedmerge=true;

select a.id,b.name 
from stu_buck a
inner join stu_buck2 b
on a.id=b.id

hiveleft join和join的效率_hive_03

 

 

2、Count(Distinct) 去重统计

数据量小的时候无所谓,数据量大的情况下,由于COUNT DISTINCT操作需要用一个Reduce Task来完成,这一个Reduce需要处理的数据量太大,就会导致整个Job很难完成,一般COUNT DISTINCT使用先GROUP BY再COUNT的方式替换

3、行列过滤

列处理:在SELECT中,只拿需要的列,如果有,尽量使用分区过滤,少用SELECT *。

行处理:在分区剪裁中,当使用外关联时,如果将副表的过滤条件写在Where后面,那么就会先全表关联,之后再过滤

4、避免笛卡尔积

 尽量避免笛卡尔积,join的时候不加on条件,或者无效的on条件,Hive只能使用1个reducer来完成笛卡尔积。