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. php链接access并查询列出

    <?php$odbc = "Driver={Microsoft Access Driver (*.mdb)};Dbq=".realpath("db.mdb" ...

  2. 若依-更换数据库-sqlite

    基础 我是在ruoyi-vue已经安装了mybatis-plus的基础上进行的修改 关于SQLite SQLite 是一个软件库,实现了自给自足的.无服务器的.零配置的.事务性的 SQL 数据库引擎. ...

  3. vue - video视频播放完后重置播放,离开页面暂停所有视频,轮播切换后暂停播放所有视频

    描述:基于vue-awesome-swiper的多视频处理 slideChangeTransitionEnd:轮播切换时暂停播放 父组件 <swiper ref="mySwiper&q ...

  4. api规范PHP,RESTful API规范(详细版)

    rest 是一种软件架构风格,如果你们的接口是 rest 接口,那么就可被认为你们的的接口是restful的,英文名词和形容词的区别. rest 接口是围绕"资源"展开的,利用HT ...

  5. Windows 隐藏 远程桌面(连接栏)

    当我们在使用远程桌面控制的时候,远程桌面工具栏遮挡视线很烦人.这时候就很有必要隐藏了! 1.全屏时显示连接栏 勾选去掉 这样子远程桌面上方的连接栏就消失了. 那么我们怎么打开呢?所以就要写下来记住了. ...

  6. marker的存储组---layerGroup

    1 <!DOCTYPE html> 2 <html lang="zh"> 3 <head> 4 <meta charset="U ...

  7. Hanlp 在Python环境中安装、介绍及使用

    Hanlp HanLP是由一系列模型与算法组成的Java工具包,目标是普及自然语言处理在生产环境中的应用.HanLP具备功能完善.性能高效.架构清晰.语料时新.可自定义的特点. 功能:中文分词 词性标 ...

  8. MongoDB升级

    因业务需要所以需要对mongoDB客户端jar包升级,在此记录一些过程 1.jar包替换,引入依赖 3.2.2: mongo-java-driver     |     4.6.1: mongo-dr ...

  9. jreg视频内容整理

    目录 5种变得开心的方法 我(曾经)想死 别再问我过得好不好了 5种变得开心的方法 浪费时间,比如打游戏,什么都不干 停止思考,什么都不要想,刷视频 独处,不要跟别人分享你的痛苦,把自己的痛苦当作世界 ...

  10. git提交命令

    链接:https://www.waimaiguai.com/technology/article/5425017来源:外卖怪 外卖怪技术学习git更新代码命令2022-08-17 02:56:11gi ...