1)MapJoin
如果不指定MapJoin或者不符合MapJoin的条件,那么Hive解析器会将Join操作转换成Common Join,即:在Reduce阶段完成join。容易发生数据倾斜。可以用MapJoin把小表全部加载到内存在map端进行join,避免reducer处理。
2)行列过滤
列处理:在SELECT中,只拿需要的列,如果有,尽量使用分区过滤,少用SELECT 。
行处理:在分区剪裁中,当使用外关联时,如果将副表的过滤条件写在Where后面,那么就会先全表关联,之后再过滤。
3)列式存储
4)采用分区技术
5)合理设置Map数
mapred.min.split.size: 指的是数据的最小分割单元大小;min的默认值是1B
mapred.max.split.size: 指的是数据的最大分割单元大小;max的默认值是256MB
通过调整max可以起到调整map数的作用,减小max可以增加map数,增大max可以减少map数。
需要提醒的是,直接调整mapred.map.tasks这个参数是没有效果的。
https://www.cnblogs.com/swordfall/p/11037539.html
6)合理设置Reduce数
Reduce个数并不是越多越好
(1)过多的启动和初始化Reduce也会消耗时间和资源;
(2)另外,有多少个Reduce,就会有多少个输出文件,如果生成了很多个小文件,那么如果这些小文件作为下一个任务的输入,则也会出现小文件过多的问题;
在设置Reduce个数的时候也需要考虑这两个原则:处理大数据量利用合适的Reduce数;使单个Reduce任务处理数据量大小要合适;
7)小文件如何产生的?
(1)动态分区插入数据,产生大量的小文件,从而导致map数量剧增;
(2)reduce数量越多,小文件也越多(reduce的个数和输出文件是对应的);
(3)数据源本身就包含大量的小文件。***
8)小文件解决方案
(1)在Map执行前合并小文件,减少Map数:CombineHiveInputFormat具有对小文件进行合并的功能(系统默认的格式)。HiveInputFormat没有对小文件合并功能。
(2)merge
// 输出合并小文件
SET hive.merge.mapfiles = true; – 默认true,在map-only任务结束时合并小文件
SET hive.merge.mapredfiles = true; – 默认false,在map-reduce任务结束时合并小文件
SET hive.merge.size.per.task = 268435456; – 默认256M
SET hive.merge.smallfiles.avgsize = 16777216; – 当输出文件的平均大小小于16m该值时,启动一个独立的map-reduce任务进行文件merge
(3)开启JVM重用
set mapreduce.job.jvm.numtasks=10
9)开启map端combiner(不影响最终业务逻辑)
set hive.map.aggr=true;
10)压缩(选择快的)
设置map端输出、中间结果压缩。(不完全是解决数据倾斜的问题,但是减少了IO读写和网络传输,能提高很多效率)
set hive.exec.compress.intermediate=true --启用中间数据压缩
set mapreduce.map.output.compress=true --启用最终数据压缩
set mapreduce.map.outout.compress.codec=…; --设置压缩方式
11)采用tez引擎或者spark引擎
12)hive数据库的数据倾斜:****
表现:在日志中,reduce的百分比卡在了99%的位置不动了,可能几分钟可以跑完的数据,半个多小时了还没结束。大部分需要计算的数据量集中在少部分运行的机器上。
- 大表和小表进行表连接的时候
第一种方法:拆分大表
例如a表有1000万数据,b表只有200万,那么可以:
select * from
(select * from a limit 5000000) a1 join b on a1.id=b.id
unoin all
select * from
(select * from a limit 5000000,5000000) a2 join b on a2.id=b.id;
第二种方法:使用mapjoin优化器 select /*+ mapjoin(表名) /
1.先打开mapjoin表连接的开关
set hive.auto.convert.join=true;
2.使用优化器进行表连接 mapjoin(小表名)
select /+ mapjoin(b) / from a join b on a.id=b.id;
将小的表格的所有数据,通过mapjoin优化器,全部读取到内存中,然后用大表的数据去匹配内存中的小表数据,达到查询加速的效果。
-
表格中有大量空值(特别是在字符串的列上)的时候
使用字符串+随机值对空值进行填充
nvl(列名,concat(‘rand’,cast(rand()*10000000 as int))) -
不合理的sql语句,在hive里面,尽量的不要使用distinct,使用group by进行去重
例如count(distinct 列名)
去重统计使用:select count(列名) from (select 列名 from 表名 group by 列名) a; -
使用一些常见的开关来优化
当数据量比较小的时候,使用本地模式进行运算(当计算的数据量超过20M(20万行左右)以后,就不要用了):
set hive.exec.mode.local.auto=true;
分组聚合计算的优化:
set hive.map.aggr=true;
负载均衡的优化:
set hive.groupby.skewindata=true;