Spark算子选择策略
摘要
1.使用reduceByKey/aggregateByKey替代groupByKey
2.使用mapPartitions替代普通map
3.使用foreachPartitions替代foreach
4.使用filter之后进行coalesce操作
5.使用repartitionAndSortWithinPartitions替代repartition与sort类操作
6.使用broadcast使各task共享同一Executor的集合替代算子函数中各task传送一份集合
7.使用相同分区方式的join可以避免Shuffle
8.map和flatMap选择
9.cache和persist选择
10.zipWithIndex和zipWithUniqueId选择
内容
1.使用reduceByKey/aggregateByKey替代groupByKey
reduceByKey/aggregateByKey底层使用combinerByKey实现,会在map端进行局部聚合;groupByKey不会
2.使用mapPartitions替代普通map
mapPartitions类的算子,一次函数调用会处理一个partition所有的数据,而不是一次函数调用处理一条,性能相对来说会高一些。但是有的时候,使用mapPartitions会出现OOM(内存溢出)的问题。因为单次函数调用就要处理掉一个partition所有的数据,如果内存不够,垃圾回收时是无法回收掉太多对象的,很可能出现OOM异常。所以使用这类操作时要慎重!
3.使用foreachPartitions替代foreach
原理类似于“使用mapPartitions替代map”,也是一次函数调用处理一个partition的所有数据,而不是一次函数调用处理一条数据。在实践中发现,foreachPartitions类的算子,对性能的提升还是很有帮助的。比如在foreach函数中,将RDD中所有数据写MySQL,那么如果是普通的foreach算子,就会一条数据一条数据地写,每次函数调用可能就会创建一个数据库连接,此时就势必会频繁地创建和销毁数据库连接,性能是非常低下;但是如果用foreachPartitions算子一次性处理一个partition的数据,那么对于每个partition,只要创建一个数据库连接即可,然后执行批量插入操作,此时性能是比较高的。实践中发现,对于1万条左右的数据量写MySQL,性能可以提升30%以上。
4.使用filter之后进行coalesce操作
通常对一个RDD执行filter算子过滤掉RDD中较多数据后(比如30%以上的数据),建议使用coalesce算子,手动减少RDD的partition数量,将RDD中的数据压缩到更少的partition中去。因为filter之后,RDD的每个partition中都会有很多数据被过滤掉,此时如果照常进行后续的计算,其实每个task处理的partition中的数据量并不是很多,有一点资源浪费,而且此时处理的task越多,可能速度反而越慢。因此用coalesce减少partition数量,将RDD中的数据压缩到更少的partition之后,只要使用更少的task即可处理完所有的partition。在某些场景下,对于性能的提升会有一定的帮助。
5.使用repartitionAndSortWithinPartitions替代repartition与sort类操作
repartitionAndSortWithinPartitions是Spark官网推荐的一个算子,官方建议,如果需要在repartition重分区之后,还要进行排序,建议直接使用repartitionAndSortWithinPartitions算子。因为该算子可以一边进行重分区的shuffle操作,一边进行排序。shuffle与sort两个操作同时进行,比先shuffle再sort来说,性能可能是要高的。
6.使用broadcast使各task共享同一Executor的集合替代算子函数中各task传送一份集合
在算子函数中使用到外部变量时,默认情况下,Spark会将该变量复制多个副本,通过网络传输到task中,此时每个task都有一个变量副本。如果变量本身比较大的话(比如100M,甚至1G),那么大量的变量副本在网络中传输的性能开销,以及在各个节点的Executor中占用过多内存导致的频繁GC,都会极大地影响性能。
因此对于上述情况,如果使用的外部变量比较大,建议使用Spark的广播功能,对该变量进行广播。广播后的变量,会保证每个Executor的内存中,只驻留一份变量副本,而Executor中的task执行时共享该Executor中的那份变量副本。这样的话,可以大大减少变量副本的数量,从而减少网络传输的性能开销,并减少对Executor内存的占用开销,降低GC的频率。
7.使用相同分区方式的join可以避免Shuffle
Spark知道当前面的转换已经根据相同的partitioner分区器分好区的时候如何避免shuffle。如果RDD有相同数目的分区,join操作不需要额外的shuffle操作。因为RDD是相同分区的,rdd1中任何一个分区的key集合都只能出现在rdd2中的单个分区中。因此rdd3中任何一个输出分区的内容仅仅依赖rdd1和rdd2中的单个分区,第三次shuffle就没有必要了。
rdd1 = someRdd.reduceByKey(...)
rdd2 = someOtherRdd.reduceByKey(...)
rdd3 = rdd1.join(rdd2)
那如果rdd1和rdd2使用不同的分区器,或者使用默认的hash分区器但配置不同的分区数呢?那样的话,仅仅只有一个rdd(较少分区的RDD)需要重新shuffle后再join。(参考自)
8.map和flatMap选择
def map[U](f: (T) ⇒ U)(implicit arg0: ClassTag[U]): RDD[U] //Return a new RDD by applying a function to all elements of this RDD.
def flatMap[U](f: (T) ⇒ TraversableOnce[U])(implicit arg0: ClassTag[U]): RDD[U] //Return a new RDD by first applying a function to all elements of this RDD, and then flattening the results.
前者的输入是一个单一数据,后者的输入数据是一个可迭代的集合。同样是执行某种映射函数,后者最终会把元素打平,即map的输入输出是一对一的,而flatMap的输出是一对多的
Spark算子选择策略的更多相关文章
- spark算子之DataFrame和DataSet
前言 传统的RDD相对于mapreduce和storm提供了丰富强大的算子.在spark慢慢步入DataFrame到DataSet的今天,在算子的类型基本不变的情况下,这两个数据集提供了更为强大的的功 ...
- Spark:常用transformation及action,spark算子详解
常用transformation及action介绍,spark算子详解 一.常用transformation介绍 1.1 transformation操作实例 二.常用action介绍 2.1 act ...
- ${mapred.local.dir}选择策略--Map Task存放中间结果
上篇说了block在DataNode配置有多个${dfs.data.dir}时的存储策略,本文主要介绍TaskTracker在配置有多个${mapred.local.dir}时的选择策略. mapre ...
- HDFS读写数据块--${dfs.data.dir}选择策略
最近工作需要,看了HDFS读写数据块这部分.不过可能跟网上大部分帖子不一样,本文主要写了${dfs.data.dir}的选择策略,也就是block在DataNode上的放置策略.我主要是从我们工作需要 ...
- (转)Spark 算子系列文章
http://lxw1234.com/archives/2015/07/363.htm Spark算子:RDD基本转换操作(1)–map.flagMap.distinct Spark算子:RDD创建操 ...
- [原创].NET 业务框架开发实战之八 业务层Mapping的选择策略
原文:[原创].NET 业务框架开发实战之八 业务层Mapping的选择策略 .NET 业务框架开发实战之八 业务层Mapping的选择策略 前言:在上一篇文章中提到了mapping,感觉很像在重新实 ...
- Spark算子总结及案例
spark算子大致上可分三大类算子: 1.Value数据类型的Transformation算子,这种变换不触发提交作业,针对处理的数据项是Value型的数据. 2.Key-Value数据类型的Tran ...
- UserView--第二种方式(避免第一种方式Set饱和),基于Spark算子的java代码实现
UserView--第二种方式(避免第一种方式Set饱和),基于Spark算子的java代码实现 测试数据 java代码 package com.hzf.spark.study; import ...
- UserView--第一种方式set去重,基于Spark算子的java代码实现
UserView--第一种方式set去重,基于Spark算子的java代码实现 测试数据 java代码 package com.hzf.spark.study; import java.util.Ha ...
随机推荐
- 丢手帕问题即约瑟夫问题的PHP解法
问题描述:n个人排成一圈.从某个人开始,依次报数,数到m的人被杀死.下一个人重新从1开始报数,数到m的人被杀死.直到剩下最后一个人. 解决思路:从数学角度去看,每一次报数决定谁去死是一个n.m的求余数 ...
- 通过GDI+绘制 验证码
只为了记录下自己的学习历程,方便日后查看 现在开始言归正传,以下为其完整代码附上 using System; using System.Collections.Generic; using Syste ...
- Ajax浅学习
写在前面:响应事件 function addEvent(obj, type, fn) { if (obj.addEventListener) { obj.addEventListener(type, ...
- tornado学习笔记18 _RequestDispatcher 请求分发器
根据Application的配置,主要负责将客户端的请求分发到具体的RequestHandler.这个类实现了HTTPMessageDelegate接口. 18.1 构造函数 定义: def __in ...
- iOS 面试总结 二
1.用三种方法生成内容为数字 1,2 ,3 的可变数组.(使用Objective-C,尽量一行代码实现) //方法一 NSMutableArray *arr1 = [[NSMutableArray a ...
- zabbix监控报错zabbix server is not running解决方法
问题描述: 布置好zabbix监控,正常运行.但是重启了虚拟机服务器之后,页面出现如下的报错,而且设置的报信息也是失效的:
- Java的四种引用方式
一.引用基本概念 从JDK1.2版本开始,把对象的引用分为四种级别,从而使程序能更加灵活的控制对象的生命周期.这四种级别由高到低依次为:强引用.软引用.弱引用.虚引用. 1.强引用(StrongRef ...
- [收藏]C++简单五子棋
#include<iostream> #include<iomanip> using namespace std; ; //棋盘行数 ; //棋盘列数 char p[X][Y] ...
- #iOS问题记录# 关于UITableViewcel的分割线去掉问题
十分清楚的记得以前在使用的时候,通过[_mTableView setSeparatorStyle:UITableViewCellSeparatorStyleNone];这一句话来达到效果的. 这次怎么 ...
- Win7网上邻居提示未授予用户在此计算机上的请求登录类型解决办法
内容简介 装了Win7之后很多人遇到这样的问题,网上邻居访问Win7的电脑时出现“未授予用户在此计算机上的请求登录类型”问题.打开“控制面板”--“管理工具”--“本地安全策略”--“本地策略 ...