HIVE调优与SQL优化

HIVE调优

1、JOIN优化
在join连接时将较小的表放于左侧,如果这个表足够的小,会完全载入到内存中,这时hive执行一个map-side join ,可以减少reduce过程
set hive.auto.convert.join=true;

hive.optimize.skewjoin=true;这个参数防止数据倾斜

set hive.skewjoin.key=100000; 这个是join的键对应的记录条数,超过这个值则会进行优化

2、本地模式
在hive中有时输入的数据量非常少,查询却非常耗时,此时开启本地模式(基本不用,数据量不会小,作为了解)

hive.exec.mode.local.auto=true
会让hive在适当的时候启用这个优化

3、并行执行
hive会将查询转化为多个阶段,默认情况下,hive只会执行一个阶段。有些阶段并非完全依赖,即a->b这种,所以可以将这些阶段并行执行,增加集群利用率
hive.exec.parallel=true

4、严格模式
开启严格模式:
1)where中需含有分区字段限制,否则不允许执行(因为不限制的话hive会扫描整个分区)
2)对于使用ORDER BY语句必须加limit(ORDERY BY会进行全局排序,运行时会将所有结果数据放入一个reduce中处理)
3)限制笛卡尔积查询

5、调整mapper和reducer个数
hive根据数据量大小确定reducer个数的 用dfs -count查看计算量输入大小 类似linux -s
set hive.exec.reducers.bytes.per.reducer=数量;

设置 hive.exec.reducers.max可以阻止某个查询小号过多的reducer资源
计算公式
(集群总Reducer槽位个数*1.5)/(执行中的查询的平均个数)

6、JVM重用
Hadoop默认使用派生JVM来执行map、reduce任务,这两可以提高利用率,但是有一个缺点,开启这个重用会一致占用task插槽,如果有job某些reduce task执行时间比其他多,那么保留的插槽会一致空闲无法被其他的job使用

set mapred.job.reuse.jvm.num.tasks=10

7、索引
可以加快group by 语句的查询速度

此处举例:Bitmap索引

create index 索引名
on table 表名称(字段)
as ‘BITMAP’
with deferred rebuild
in table 索引后的表明
comment ‘描述内容’;

8、推测执行
推测执行:加速获取单个task结果以及进行侦测较慢的TaskTracker加入黑名单的方式来提高整体的任务执行效率
set mapred.map.tasks.speculative.execution=true
set mapred.reduce.tasks.speculative.execution=true

9、group by优化
开启
set hive.group.skewindata=true; 防止数据倾斜

set hive.groupby.mapaggr.checkinterval=100000; 这个是group的键对应的记录条数超过这个值则会进行优化

10、count distinct
优化前:select count(distinct 字段) from 表名;
优化后:select count(1) from (select 字段 from 表名 group by id) 别名;

注释:count(1)用于计算符合条件的行数

11、小文件合并
set hive.input.format=org.apache.hadoop.hive.ql.io.CombineHiveInputFormat

12、sql优化
1)sql中使用or必须用()括起来,否则可能引起无分区限制
2)尽早的过滤数据,减少每个阶段的数据量,分区表要加分区限制
select … from A join B
on A.key = B.key where A.id>5 and B.id<5 and A.dt=‘20200420’ and B.dt=‘20200420’;
改写为:
select … from (select … from A where dt=‘20200420’ and id>5) a join ( select … from B where dt=‘20200420’ and id < 5) b on a.key = b.key;

3)如果union all的部分个数大于2,应该拆成多个insert into 语句
insert overwite table 表名 partition (dt= …)
select … from (
select … from A
union all
select … from B
union all
select … from C
… …
) Z
where dt=‘20200420’
改写为
insert into table 表明 partition (dt= …)
select … from A
where …;

以此类推

4)left semi join
hive中不支持
select s.a,s.b,s.c from 表名 s where s.a,s.b in (select z.a,z.b from 表名 z);
可以使用
select s.a,s.b,s.c from 表名 s left semi join 表名 z on s.a=z.a and s.b=z.b

5)in 与 not in使用
in改写:select a.id,a.name from a join b on a.id=b.id where b.name is null; 或者用left semi join
not in 改写:select a.id,a.name from a join b on a.id=b.id where b.name is not null 、


可能不全,请大佬们在留言区补传


版权声明:本文为qq_43405333原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。