减少distinct:使用distinct容易造成数据倾斜问题,使用group by的子查询代替它。
map任务数量优化: 实际业务中往往存在大量的分区表,每个分区表都实际存储一定量的文件,其中必然有些分区的数据量很少。
正常读取时往往有多少个文件就创建多少个map,此时可以通过设置一些参数,让sql语句在执行前先合并表文件。
-参数: mapred.min.split.size.per.node = {设置一个节点中分片至少的大小}byte mapred.min.split.size.per.rack= {设置一个交换机中分片至少的大小}byte mapred.max.split.size = {设置分片的最大大小}byte hive.input.format=org.apache.hadoop.hive.ql.io.CombineHiveInputFormat 设置hive先合并文件再执行
-效果: 假设我全部设置为100000000(相当于100M),经过配置后,hive会首先合并文件,切分成各种100M,最后再把剩下来的各个节点上的散碎数据合并到一起再生成几个分片。
还有一种情况,当一个map任务中处理数据量很大时(大小很小,但是条数很多),可以采用分桶法,先用一个查询语句把该表数据查出来分桶写入,再使用这个分桶表。
相当于增加map任务数量,增加并行度。 并行度优化:
1.手动设置reduce数量 mapred.reduce.tasks
2.避免全局的聚合函数,使用聚合函数尽量要分组
3.避免全局的order by,有时候全局排序很难避免,但可以根据topN需求,再各个分区中只留下N个值,再进行全局排序。
4.避免笛卡尔积 5.设置mapTask分片大小 小文件问题:
1.避免产生小文件:少用动态分区、根据需求使用reduce
2.使用Sequencefile作为表存储格式,不要用textfile,在一定程度上可以减少小文件
3.使用hadoop archive命令把小文件进行归档
4.重建表,建表时减少reduce数量
5.参数设置: hive.merge.mapfiles = true设置map端输出合并 hive.merge.mapredfiles = true设置reduce输出合并hive.merge.size.per.task = 25610001000 设置合并文件的大小hive.merge.smallfiles.avgsize=16000000 设置当平均大小小于该值时合并 存储格式
1.使用ORCfile存储,可以显著提高join操作的查询速度
2.使用压缩格式存储,可以显著降低网络IO和存储大小 使用map端join 使用tez作为默认引擎 使用向量化查询:一次执行1024行数据的操作 hive.vectorized.execution.enabled = true; hive.vectorized.execution.reduce.enabled = true;
设置本地模式、并行模式(自动并行非依赖阶段)、严格模式开启JVM重用,总结;减少distinct设置读取时合并小文件和合理拆分大文件,优化并行度 设置存储格式和压缩格式 设置输出时合并小文件 设置map端JOIN更换引擎,设置本地模式、并行模式、严格模式开启JVM重用 开启推测执行