本文共 3329 字,大约阅读时间需要 11 分钟。
案例:
val rdd1 = sc.textFile("hdfs://zzy/hello.txt")rdd1.map(...)val rdd2 = sc.textFile("hdfs://zzy/hello.txt")rdd2.reduce(...)
这里条用了两次textFile,并且读取的是同一个文件,造成了多次的磁盘读取,如果是hi同一个文件,读取一次即可。
错误演示:
//由于业务需要,对rdd1执行了一个map操作,创建了一个rdd2,而rdd2中的数据仅仅是rdd1中的value值而已,也就是说,rdd2是rdd1的子集。 val list=List(("math",18),("hbase",18),("hive",22),("hive",18)) val listRDD: RDD[(String, Int)] = sc.parallelize(list) val listRDD2=listRDD.map(kv=>kv._2)
正确做法:
//在进行第二个map操作时,只使用每个数据的kv._2,也就是rdd1中的value值,即可 val list=List(("math",18),("hbase",18),("hive",22),("hive",18)) val listRDD: RDD[(String, Int)] = sc.parallelize(list) listRDD.reduceByKey(_+_).map(kv=>kv._2)
案例:
val list=List(("math",18),("hbase",18),("hive",22),("hive",18)) val listRDD: RDD[(String, Int)] = sc.parallelize(list) listRDD.cache() listRDD.map(kv=>kv._1) listRDD.map(kv=>kv._2) listRDD.reduceByKey(_+_)
注意:程序运行过程中的数据放置在内存中,如果程序执行完成,一般都会释放内存的资源。如果程序执行过程中,生成了一些中间结果是另一个程序需要使用的数据时,那么就可以把该数据持久化到内存或者磁盘中,避免不必要的重复计算,一般的一个RDD如果被重复使用2~3次以上,就需要持久化。
因为在spark作业的运行过程中,最消耗性能的地方就是shuffle过程,原因:
// 因为两个RDD中,相同的key都需要通过网络拉取到一个节点上,由一个task进行join操作val rdd3 = rdd1.join(rdd2)
使用Broadcast+map的join操作:
// 使用Broadcast将一个数据量较小的RDD作为广播变量。val rdd2Data = rdd2.collect()val rdd2DataBroadcast = sc.broadcast(rdd2Data)
注意:广播变量的对象一定不能太大,如果太大的话可能会导致OOM,当然广播变量不能是一个RDD,可以通过一些action算子,将RDD转化成为集合然后进行广播。
案例:
val hdfsRDD: RDD[String] = sc.textFile("hdfs://zy/data/word.txt") //Map是每一条调用一次 hdfsRDD.map(kv=>{ //获取数据库的连接 connect=Connect.getconnect() connect.insert(kv) }) //Mappartitions每一个分区调用一次。 hdfsRDD.mapPartitions(partition=>{ if(!partition.isEmpty){ //获取数据库的连接 connect=Connect.getconnect() partition.foreach(mes=>{ connect.insert(mes) }) } })
以上的案例虽然都是插入数据,但是使用map是每一条记录都需要创建一个连接,而使用mappartition只需要每一个分区创建一个即可。
优势见:
默认的情况下,spark支持java原生的序列化机制,使用KryoSerolizar可以优化序列化和反序列化的性能
案例:// 设置序列化器为KryoSerializer。conf.set("spark.serializer", "org.apache.spark.serializer.KryoSerializer")// 注册要序列化的自定义类型。conf.registerKryoClasses(Array(classOf[MyClass1], classOf[MyClass2]))
在java中有三种对象比较消耗内存:对象、字符串、集合类型。
对象:每一个java对象都有对象头,引用等额外的信息,因此比较占用内存空间字符串:每一个字符串内部都有一个字符数组以及长度等额外信息集合:HashMap、LinkedList等,因为集合类型内部通常会使用一些内部类来封装集合元素。所以我们遵循:尽量少用这三种类型,当然使用基本数据类型代替字符串,使用字符串代替对象,使用对象代替集合。本博文参考至美团的spark调优:
转载于:https://blog.51cto.com/14048416/2338607