问题:后面的优化问题遇到了瓶颈。原因如下:
1.观察到/tmp的使用率一度达到98%,如果再在某一个一个语句中增加一个分隔符设置,还是会出现磁盘空间不足问题;
2.在增加分隔符之前,成功的把主要结果数据存储到内存中,使用序列化与压缩,查看其大小为9.8GB,全部数据是这两倍左右。
3.partition分布不均匀时候,会造成shuffle时消耗大量磁盘空间;
4.使用不同的api,会有不同shuffle代价;
5.如何配置shuffle时磁盘与内存的使用率,以平衡空间与时间消耗需要继续实验;
6.partiton、cores、reducer number等等都会影响shuffle文件数量,需要选取合适的配置
7.数据量为9亿个,估算为12GB,40G的磁盘提供shuffle还会溢出,这个需要根据1-3查明原因。
初步解决了磁盘空间不足与cache空间不足问题。调优知识概括如下:
1.分区:每个分区不能太大以免OOM,分区大小尽量均匀分布在各个executor,以免数据倾斜;2.序列化与压缩:序列化及压缩可以缓解存储压力,官方建议使用非默认的Kryo序列化较高效,但其参数设置依赖于被序列化对象的大小,需要摸索经验;
3.JVM:设置Eden、Old区域的大小,以降低GC耗时、增大cache可利用内存空间;
4.探究了总内存与可利用的内存的关系,发现一个隐含系数0.86±0.02之间,官方文档把这个系数隐藏了,以避免给用户带来困惑,cache所能利用的内存一定低于这个系数限定的内存。
5.修改了部分程序以降低shuffle写入磁盘的数据量、根据聚合函数中先后次序不确定的问题,修改了部分代码。
查看各个分区数量的语句:
val each_part_num = a_all_device_kv.mapPartitions{e =>
{var result = List[Int]();var i:Int = 0;while (e.hasNext){e.next;i += 1}
;result.::(i).iterator}}