大数据调优汇总

1.优化问题

Hive的优化:

1. 当有join操作的时候, 将小表加入到缓存, 在map端进行join

2.     分区分桶(分区表相当于hive的索引,加快查询速度) (两个表join的时候,如果两个表在相同列上有分桶操作,会减少join数据量【要求两个表的桶数量要相同或成倍数】)

3.     行列过滤(只取需要的列, 先将行过滤, 再join)

4.     合理设置map数

5.     小文件合并,减少map数

6.     合理设置reduce的个数(有多少个reduce就会有多少个文件输出, 如果生成的都是小文件, 那么作为下次输入时,就会面对很多小文件的问题)

7. 并行计算,stage不依赖的时候可以并行计算
SQL调优
1.	count distinct优化
		不要使用count (distinct   cloumn) ,而要使用子查询实现count(distinct)
		select count(1) from (select id from tablename group by id) tmp;
2.	Distinct 与 group by的区别
Distinct 是对全局/全表进行去重, shuffle后只会在一个reduce中进行, 容易发生数据倾斜
Group by 是分组去重, 有多少个task就会生成多少个reduce, 性能更高
3.	如果需要根据一张表的字段约束另一个张表,用in代替join
		select id,name from tb1  a join tb2 b on(a.id = b.id);
		可优化为
		select id,name from tb1 where id in(select id from tb2); in 要比join 快
4.where语句优化
		select m.cid,u.id from order m join customer u on( m.cid =u.id )where m.dt='20180808';
		可优化为
		select m.cid,u.id from (select * from order where dt='20180818') m join customer u on( m.cid =u.id);
5.union优化
		尽量不要使用union (union 去掉重复的记录)而是使用 union all 然后在用group by 去重
6.消灭子查询内的 group by 、 COUNT(DISTINCT),MAX,MIN。 可以减少job的数量。

spark优化:
1.提高并行度 设置分区数的方式
    如果我们将分区数设置为50个,那每一个task处理的数据是0.2G,同一时间,50个task都可以运行. 然后整个运行效率就有所提升. 在项目中分区数一般设置为CPU核数的2-3倍
    设置分区的方式:
        对于sparkcore:
        在代码中设置.config("spark.default.parallelism",450) 
    通过repartition算子进行重分区
        对于sparksql:
        在代码中设置.config("spark.sql.shuffle.partitions",450) sparksql参数
        repartition,coalese
2.增加资源
    --executor-memory
    --executor-cores
    --num-executor
3.序列化 项目种一般采用Kryo序列化
4.本地化等待时间
	场景:比如spark任务有2个stage,第一个stage运行完成之后有数据,第二个stage需要第一个stage的数据
	如果HDFS的block块在node01上面,spark任务在读取HDFS文件进行处理的时候,默认将task分配node01,但是如果node01没有资源了,这个时候spark有一个等待时间spark.locality.wait,如果超过等待时间,那么spark就会在另外worker上启动task,然后从node01拉取数据进行计算
5.内存比例调优
    --executor-memory 1G
    内存会分为执行与存储的内存区域,用户自定义内存区域和spark保留区
    spark2.0以前,执行区和存储区是固定的,如果在执行任务期间,执行区空间不足,而存储空间有剩余的时候,它并不会占用存储的空间
    spark2.0以后,执行与存储区是可以动态调整,就是说如果执行区空间不足,而存储区有剩余,那么这时候,spark就会将存储区剩余空间给执行区使用.同样,如果存储区空间不足,而执行区剩余,那么spark会将执行区空闲内存给存储区使用
注意:
    a.如果在任务运行前期,执行空间不足,而存储区有剩余的时候,执行区会占用存储空间,但是如果在任务后期,发现存储区空间不足,这时候不会驱逐执行区占用的空间
    b.如果在任务运行前期,执行区有剩余,存储区不足,存储区会占用执行区的空间,但是如果在任务后期,发现执行区空间也不足,会驱逐存储占用的空间,将部分数据保存在磁盘.因为执行去的数据更重要
    内存参数调整:
        spark.memory.fraction="0.6" 指定spark执行与存储的内存比例
        sparrk.memory.storageFraction="0.5" 指定spark存储的内存比例
    如果webui界面看到GC时间特别长,证明存储对象的内存空间过小,这时候需要增大内存.增大内存有两种方式:一是直接将executor-memory设置大一点,二是将执行与存储的内存比例调小
6.广播变量
    spark.sparkcontext.broadcast(广播数据)
    spark.sql.autoBroadcastJoinThreshold 要广播出去的小表的限制
    在工作中一般需要通过spark.sql("cache table 表")将表缓存之后才能正常广播出去
7.推测机制
8.代码层调优:
8.1数据倾斜 另外再写
8.2采用高性能算子:
	reduceByKey代替groupByKey
	mapPartition代替map
	foreachPartition代替foreach
GC的过程:
1.初始创建对象的时候,对象放在Eden种
2.随着时间的流逝,Eden种存放的对象越来越多,当Eden区域满了,会进行minor GC,会将Eden种还在使用的对象放入到servivor0中,不需要的对象清楚掉.清除掉之后的Eden就变空了
3.Eden中有可以重新接纳对象,随时间的流逝,Eden中存放的对象越来越多,当Eden区域满了,又进行GC ,会将Eden与servivor中还在使用的对象放入到survivor1中,Eden与servivor中使用的对象清除掉
4.循环第三个步骤
5.当survivor中空间不足,会将还在使用的对象放入到老年代中
6.循环3-5步骤
7.随着时间流逝,老年代中空间不足,这时候就需要full GC , Full GC的时间短则几分钟,长的十几分钟.期间,进行对暂停一切操作,优先GC, 这个时候可能还会出现拉取shuffle数据失败

如果在GC的时候拉取shuffle数据失败,会有一个重试次数,如果重试之后,任然没有拉取到数据,任务报错,停止执行
针对这个问题,可以调整拉取shuffle失败的参数:
spark.shuffle.io.maxRetries=6 shuffle拉取数据失败的时候最大重试次数
spark.shuffle.io.retryWait=10s拉取失败的时候,每次重试的时间间隔

发布了25 篇原创文章 · 获赞 4 · 访问量 710

猜你喜欢

转载自blog.csdn.net/qq_43149023/article/details/104094725