pySpark RDD基本用法

RDD的全称是:Resilient Distributed Dataset (弹性分布式数据集),它有几个关键的特性:

RDD是只读的,表示它的不可变性。

可以并行的操作分区集合上的所有元素。

每个RDD的内部,有5个主要特性:

  • A list of partitions (一个分区列表,可以获取所有的数据分区)
  • A function for computing each split(对给定的分区内的数据进行计算的function)
  • A list of dependencies on other RDDs (一个RDD所依赖的父RDD列表)
  • Optionally, a Partitioner for key-value RDDs (可选:如何进行K-V的RDD分区)
  • Optionally, a list of preferred locations to compute each split on(可选:数据做运算时最优的地址,即数据本地性)

1.RDD的三种基本运算

  • Transformation(转换)

    概念:

    将一个RDD通过一系列操作变为另一个RDD的过程,这个操作可能是简单的加减操作,也可能是某个函数或某一系列函数。

注:所有Transformation函数都是Lazy(惰性的),不会立即执行,需要Action函数来触发

Transformation操作不会触发真正的计算,只会建立RDD的关系图

  • Action(动作)

    概念:

    Action操作代表依次计算的结束,返回值不是RDD,将结果返回到Driver程序或输出到外部(文件或文件夹)。

注:所有Action函数立即执行(Eager),比如reduce、saveAsTextFile、count等。

所以Transformation只是建立计算关系,Action才是实际的执行者。

每个Action操作都会形成一个DAG调用SparkCoutext的runJob方法向集群提交请求,所以每个Action操作都对应一个DAG/Job。

  • Persisitence(持久化)

    概念:

    Persisitence操作对于那些会重复使用的 RDD,可以将RDD"持久化"在内存中以供后续使用,以提高执行性能。

注:持久化算子有三种,cache,persist,checkpoint,以上算子都可以将RDD持久化,持久化的单位是partition。cache和persist都是懒执行的。必须有一个action类算子触发执行。checkpoint算子不仅能将RDD持久化到磁盘,还能切断RDD之间的依赖关系。

2 常用算子使用实例

python中将数据抽象成4大数据结构,分别是tuple,list,dict,set。再粗分下,又可以分成list和k-v两种数据结构。针对这两种数据机构,spark中都有相应的算子。

初始化pyspark代码:

  import time
import argparse from pyspark import SparkContext, SparkConf
from pyspark.sql.dataframe import DataFrame
from pyspark.sql.session import SparkSession
import json from pyspark.sql import HiveContext
from pyspark.sql import SQLContext sparkconf = SparkConf().setAppName("Python Spark2").set("spark.ui.showConsoleProgress", "false")\
.set("spark.serializer","org.apache.spark.serializer.KryoSerializer")\
.set("hive.exec.dynamici.partition",True)\
.set("hive.exec.dynamic.partition.mode","nonstrict") spark = SparkSession.builder.config(conf=sparkconf).enableHiveSupport().getOrCreate()
sc = spark.sparkContext

2.1基本RDD运算

2.1.1初始函数

使用parallelize函数初始化一个rdd:

  intRDD = sc.parallelize([1,2,3,4,5,6])
intRDD.collect()
:[1, 2, 3, 4, 5, 6]

parallelize,本意是平行化的意思,使数据生成于各个计算节点,用于并行计算的意思。还可以使用直接读txt文件的方式来:

  rdd = sc.textFile(file,3)

2.1.2 map函数

再使用map函数,对各个节点做相应的运算。map函数可以遍历所有的节点,生成另外一个RDD。

  intRDD.map(lambda x:x+1).collect()
:[2, 3, 4, 5, 6, 7]

2.1.3 filter函数

filter函数可以对RDD内的元素进行筛选,并产生新的RDD。

  intRDD.filter(lambda x:x>4).collect()
:[5, 6]

2.1.4 distinct函数

distinct函数对RDD内的元素进行去重复操作。并不产生新的RDD。

  intRDD = sc.parallelize([1,2,3,4,5,6,6])
intRDD.distinct().collect()
:[1, 2, 3, 4, 5, 6]

2.1.5 groupby运算

groupby运算可以通过匿名函数将数据分为多个List。

  intRDD = sc.parallelize([1,2,3,4,5,6,6])
gRDD = intRDD.groupBy(lambda x: "big" if(x>4) else "small").collect()
print(gRDD)
:[('big', <pyspark.resultiterable.ResultIterable object at 0x7f1970214640>), ('small', <pyspark.resultiterable.ResultIterable object at 0x7f1951f15ee0>)]
print(list(gRDD[0][1]))
:[5, 6, 6]

2.2 多个RDD"转换"运算

RDD支持求并集,交集,差集和笛卡尔积运算。

  intRDD1 = sc.parallelize([1,2])
intRDD2 = sc.parallelize([3,4,5])
intRDD3 = sc.parallelize([5,6,6])
intRDD4 = intRDD1.union(intRDD2).union(intRDD3).collect() #并集
print(intRDD4)
:[1, 2, 3, 4, 5, 5, 6, 6] intRDD5 = intRDD2.intersection(intRDD3).collect()#交集
print(intRDD5)
:[5] intRDD6 = intRDD2.subtract(intRDD3).collect()#差集
print(intRDD6)
:[3, 4] intRDD7 = intRDD1.cartesian(intRDD3).collect()#笛卡尔积
print(intRDD7)
:[(1, 5), (1, 6), (1, 6), (2, 5), (2, 6), (2, 6)]

2.3 基本的action运算

2.3.1 读取运算

  intRDD = sc.parallelize([1,2,3,4,5,6,6])
print(intRDD.take(1))
print(intRDD.first())
print(intRDD.takeOrdered(3))
print(intRDD.takeOrdered(3,lambda x:-x)) :[1]
:1
:[1, 2, 3]
:[6, 6, 5]

2.3.2 统计功能

  print(intRDD.stats())
:(count: 7, mean: 3.857142857142857, stdev: 1.8070158058105026, max: 6.0, min: 1.0)

2.4基本K-V RDD运算

Spark RDD 支持键值(K-V)运算,K-V运算也是Map/Reduce的基础。

2.4.1 同样的初始化方法

  intRDD = sc.parallelize([(1,2),(3,2),(4,5)])
intRDD.collect()
:[(1,2),(3,2),(4,5)]

2.4.2 filter函数

filter算子的入参是tuple,可以用x[0]和x[1]区分两个值。

  intRDD = sc.parallelize([(1,2),(3,2),(4,5)])
intRDD.filter(lambda x:x[0] > 3).collect()
:[(4, 5)]

2.4.3 mapValues函数

需要注意的是mapValues的入参是value,返回值也是value。

  intRDD = sc.parallelize([(1,2),(3,2),(4,5)])
intRDD.mapValues(lambda x:x+1).collect()
:[(1, 3), (3, 3), (4, 6)]

2.4.4 sortByKey函数

通过key值来做排序

  intRDD = sc.parallelize([(1,2),(3,2),(4,5)])
intRDD.sortByKey().collect()
intRDD.sortByKey(ascending = False).collect() :[(1, 3), (3, 3), (4, 6)]
:[(4, 5), (3, 2), (1, 2)]

2.4.5 reduceByKey函数

通过key来归纳数据

  intRDD = sc.parallelize([(1,2),(3,2),(4,5),(1,6)])
intRDD.reduceByKey(lambda x,y:x+y)
intRDD.collect()
:[(1,8),(3,2),(4,5)]

2.5 多个 K-V RDD运算

2.5.1 join运算

创建两个RDD通过join做运算拼接

  intRDD1 = sc.parallelize([(1,2),(3,2),(4,5),(1,6)])
intRDD2 = sc.parallelize([(1,2)])
intRDD1.join(intRDD2).collect()
:[(1, (2, 2)), (1, (6, 2))]

默认的join运算是通过intRDD1.key=intRDD2.key做运算的,生成一个新的RDD,key值不变,value值为tuple类型,做值得聚合。

2.5.2 leftOuterJoin运算

创建两个RDD通过leftOuterJoin做运算拼接

  intRDD1 = sc.parallelize([(1,2),(3,2),(4,5),(1,6)])
intRDD2 = sc.parallelize([(1,2)])
intRDD1.leftOuterJoin(intRDD2).collect()
:[(1, (2, 2)), (1, (6, 2)), (3, (2, None)), (4, (5, None))]

leftOuterJoin运算是通过intRDD1的key做left join运算的,生成一个新的RDD,key值为intRDD1的key,value值为tuple类型,做值的聚合。

2.5.3 rightOuterJoin运算

创建两个RDD通过rightOuterJoin做运算拼接

  intRDD1 = sc.parallelize([(1,2),(3,2),(4,5),(1,6)])
intRDD2 = sc.parallelize([(1,2)])
intRDD1.rightOuterJoin(intRDD2).collect()
[(1, (2, 2)), (1, (6, 2))]

rightOuterJoin运算是通过intRDD2的key做right join运算的,生成一个新的RDD,key值为intRDD2的key,value值为tuple类型,做值的聚合。

2.5.4 subtractByKey运算

subtractByKey会清理掉key相同的值:

  intRDD1 = sc.parallelize([(1,2),(3,2),(4,5),(1,6)])
intRDD2 = sc.parallelize([(1,9)])
intRDD1.subtractByKey(intRDD2).collect()
:[(3, 2), (4, 5)]

2.6 K-V 的 action 运算

K-V 的RDD同样支持first等运算,但是也支持一些只有K-V情况下的值。

2.6.1 collectAsMap 运算

可以将输出的值转换成map,但是需要注意的是会将key重复的值抹掉。

  intRDD1 = sc.parallelize([(1,2),(3,2),(4,5),(1,6)])
print(intRDD1.collectAsMap())
:{1: 6, 3: 2, 4: 5}

2.6.2 lookup 运算

通过key值查找对应的value值:

  intRDD1 = sc.parallelize([(1,2),(3,2),(4,5),(1,6)])
print(intRDD1.lookup(1))
:[2, 6]

2.7 RDD持久化

如果我们相对一个RDD进行复用操作的时候,基于RDD的特性,当以rdd通过transformation转化为另外一个rdd的时候,前面的rdd就会被自动释放,此时还想在原来的rdd身上进行其它操作,需要从源头进行数据计算,这样效率自然会降低。为了能够在rdd重用的时候,直接从内存中加载相关数据,所以我们需要缓存算子(persist/cache)将rdd数据持久化到内存等等其它地方。

  • MEMORY_ONLY RDD中所有的数据都会以未经序列化的java对象的格式优先存储在内存中,如果内存不够,剩下的数据不会进行持久化。很容易出OOM=OutOfMemoryException异常。java的gc频率和对象个数成正比。gc的时候会stop-the-world。

  • MEMORY_ONLY_SER 和MEMORY_ONLY的操作几乎一致,唯一的区别是在内存中存储的不在是未经序列化的java对象,是序列化之后的数据,rdd经过序列化之后,每一个partition就只有一个字节数组,也就是说一个partition就是一个java对象。

  • MEMORY_AND_DISK 和MEMORY_ONLY的唯一区别在于,MEMORY_ONLY不会持久化哪些在内存中持久化的数据,MEMORY_AND_DISK会将哪些在内存中保存不下的数据保存到磁盘中。

  • MEMORY_AND_DISK_SER 就比MEMORY_AND_DISK多了一点,存储的是序列化的java对象

  • DISK_ONLY 磁盘存储,效率太低,一般不用XXXXX_2(MEMORY_ONLY_2等等) 是在上述所有操作的基础之上进行了一个备份。从安全、高可用的角度上考虑,如果备份所消耗的时间,比数据丢失之后从源头重新计算一遍的代价小,我们才考虑使用Xxxx_2。

  • OFF_HEAP 非堆。上述所有的操作都会使用Spark自身的内存资源,所以为了给计算提供足够的资源,可以将持久化的数据保存到非executor中。常见的OFF_HEAP:Tachyon/Alluxio

    from pyspark import StorageLevel
    intRDD1.persist(storageLevel=StorageLevel.MEMORY_ONLY)
    intRDD1.unpersist()

pySpark RDD基本用法的更多相关文章

  1. Spark核心类:弹性分布式数据集RDD及其转换和操作pyspark.RDD

    http://blog.csdn.net/pipisorry/article/details/53257188 弹性分布式数据集RDD(Resilient Distributed Dataset) 术 ...

  2. [PySpark] RDD programming on a large file

    重难点 一.parallelize 方法 一般来说,Spark会尝试根据集群的状况,来自动设定slices的数目.然而,你也可以通过传递给parallelize的第二个参数来进行手动设置. data_ ...

  3. [Pyspark]RDD常用方法总结

    aggregate(zeroValue, seqOp, combOp) 入参: zeroValue表示一组初值 Tuple seqOp表示在各个分区partition中进行 什么样的聚合操作,支持不同 ...

  4. Cheat Sheet pyspark RDD(PySpark 速查表)

  5. PySpark Rdd Cheat Sheet Python

  6. pyspark学习笔记

    记录一些pyspark常用的用法,用到的就会加进来 pyspark指定分区个数 通过spark指定最终存储文件的个数,以解决例如小文件的问题,比hive方便,直观 有两种方法,repartition, ...

  7. PySpark 大数据处理

    本文主要介绍Spark的一些基本算子,PySpark及Spark SQL 的使用方法. 虽然我从2014年就开始接触Spark,但几年来一直没有真正地学以致用,时间一久便忘了如何使用,直到在工作中用到 ...

  8. [Spark][python]RDD的collect 作用是什么?

    [Spark][Python]sortByKey 例子的继续 RDD的collect() 作用是什么? “[Spark][Python]sortByKey 例子”的继续 In [20]: mydata ...

  9. [Dynamic Language] pyspark Python3.7环境设置 及py4j.protocol.Py4JJavaError: An error occurred while calling z:org.apache.spark.api.python.PythonRDD.collectAndServe解决!

    pyspark Python3.7环境设置 及py4j.protocol.Py4JJavaError: An error occurred while calling z:org.apache.spa ...

  10. Spark算子与RDD基本转换

    map 将一个RDD中的每个数据项,通过map中的函数映射变为一个新的元素. 输入分区与输出分区一对一,即:有多少个输入分区,就有多少个输出分区. flatMap 属于Transformation算子 ...

随机推荐

  1. 【转载】python解决文本乱码问题及文本二进制读取后的处理

    转自:https://blog.csdn.net/u011316258/article/details/50450079 python解决文本乱码问题及文本二进制读取后的处理 吲哚乙酸 当文本中含有很 ...

  2. 负载均衡做集群时关于的session不均衡的解决方案

    从用户端来解释,就是当一个用户第一次访问被负载均衡代理到后端服务器A并登录后,服务器A上保留了用户的登录信息:当用户再次发送请求时, 根据负载均衡策略可能被代理到后端不同的服务器,例如服务器B,由于这 ...

  3. Django views.py 增,删,改

    from django import forms from django.shortcuts import render, redirect from app01 import models # Cr ...

  4. uni-app (uView) select下拉框添加模糊搜索

    先看效果: 因为uniapp内置的下拉查询是没有输入模糊搜索的,有的列表选项过多时还是需要这个搜索功能,所以只能自己筛选 (前台.后台两种方法). 下面是代码: <template> &l ...

  5. SAP 采购订单行项目客制化字段增强

    需求: 在采购订单行项目中新增客制化字段,区分采购的项目中的物料是量产还是研发物料 开发步骤 主要使用二代增强出口:MM06E005 创建增强项目 事务码T-code:CMOD 创建项目ZEMM001 ...

  6. 2022年了!还在用定时器实现动画?赶紧试试requestAnimationFrame吧!

    前言 作为一名前端开发者,相信你一定接触过动画.还记得最开始学习前端时,我们曾尝试使用 JS 实现各种动画效果,比如轮播图等等.随着前端技术的不断更新,我们实现动画的方式变得多种多样了,比如使用JS. ...

  7. List<Object>集合获取指定属性最大值的对象

    List<Vo> list = dao.selectList();if(CollectionUtils.isNotEmpty(list)) { Optional<Vo> max ...

  8. chatGPT搭建之旅

    昨天接到领导需求,要我搭建一个chatGPT玩玩,并给了一个链接地址:https://gitee.com/RockChin/QChatGPT 然后历经千辛万苦,熬了一宿终于搭建了,中途踩了各种大坑小坑 ...

  9. Unity打包xcode修改工程配置代码

    1 using System.IO; 2 using UnityEngine; 3 using UnityEditor; 4 using UnityEditor.iOS.Xcode; 5 using ...

  10. django的模型层(二)

    django的模型层(二) 一 创建模型 from django.db import models # Create your models here. class Author(models.Mod ...