pySpark RDD基本用法
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基本用法的更多相关文章
- Spark核心类:弹性分布式数据集RDD及其转换和操作pyspark.RDD
http://blog.csdn.net/pipisorry/article/details/53257188 弹性分布式数据集RDD(Resilient Distributed Dataset) 术 ...
- [PySpark] RDD programming on a large file
重难点 一.parallelize 方法 一般来说,Spark会尝试根据集群的状况,来自动设定slices的数目.然而,你也可以通过传递给parallelize的第二个参数来进行手动设置. data_ ...
- [Pyspark]RDD常用方法总结
aggregate(zeroValue, seqOp, combOp) 入参: zeroValue表示一组初值 Tuple seqOp表示在各个分区partition中进行 什么样的聚合操作,支持不同 ...
- Cheat Sheet pyspark RDD(PySpark 速查表)
- PySpark Rdd Cheat Sheet Python
- pyspark学习笔记
记录一些pyspark常用的用法,用到的就会加进来 pyspark指定分区个数 通过spark指定最终存储文件的个数,以解决例如小文件的问题,比hive方便,直观 有两种方法,repartition, ...
- PySpark 大数据处理
本文主要介绍Spark的一些基本算子,PySpark及Spark SQL 的使用方法. 虽然我从2014年就开始接触Spark,但几年来一直没有真正地学以致用,时间一久便忘了如何使用,直到在工作中用到 ...
- [Spark][python]RDD的collect 作用是什么?
[Spark][Python]sortByKey 例子的继续 RDD的collect() 作用是什么? “[Spark][Python]sortByKey 例子”的继续 In [20]: mydata ...
- [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 ...
- Spark算子与RDD基本转换
map 将一个RDD中的每个数据项,通过map中的函数映射变为一个新的元素. 输入分区与输出分区一对一,即:有多少个输入分区,就有多少个输出分区. flatMap 属于Transformation算子 ...
随机推荐
- pdf.js打开后的pdf文件
可用pdf.js在h5打开pdf文件.注意,在本地打不开,一定要在部署环境. 方法:<a href="../../pdf/web/viewer.html?file=../../pdf/ ...
- python之定时任务APScheduler
一.APScheduler APScheduler全称Advanced Python Scheduler 作用为在指定的时间规则执行指定的作业. 指定时间规则的方式可以是间隔多久执行,可以是指定日期时 ...
- Oracle 11g 单机服务器ASM部署
Oracle oracle,相比都有所了解,是一家企业级的数据库公司(收费),上图是oracle官网,也是对外的服务平台 oracle有自己独特的安装方式:ASM : 自动存储管理(ASM,Au ...
- golang实现简单的聊天室
一.server端 package main import ( "fmt" "net" ) var message = make(chan string) ty ...
- Linux常用的性能分析
参考文档:https://www.runoob.com/w3cnote/linux-common-command-2.html 一.ps -aux ps -aux ps -ef -a:所有进程. -u ...
- virtualenvwrapper使用命令
virtualenvwrapper使用命令 创建虚拟环境:mkvirtualenv + test1 查看虚拟环境:lsvirtuslenv 删除虚拟环境:rmvirtualenv + test1 退出 ...
- 数值分析之解线性方程组的直接方法 5.X
矩阵 谱分解 设 \(\boldsymbol{A}=a_{i j} \in \mathbb{R}^{n \times n}\) , 若存在数 \(\lambda\) (实数或复数) 和非零向量 \(\ ...
- c++ class派生与多态
目录 类继承和类派生 继承时名字遮蔽 基类和派生类的构造函数 构造函数调用顺序 基类和派生类的析构函数 多重继承 虚继承和虚基类 将派生类赋值给基类(向上转型) 将派生类指针赋值给基类指针. 将派生类 ...
- cat /dev/null > file后,ls查看文件大小未减小,du查看变为0
一句话总结: 其他程序正在使用command > file写入文件:将command程序kill后使用command >> file写入文件,即可在command写入file时,用c ...
- uniapp 开发遇到的问题
1. App平台IOS端软键盘上方横条去除方案(禁用键盘上的^) 在 pages.json 中配置 style配置 "app-plus": { "softinputNav ...