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算子 ...
随机推荐
- word2021自带viso屏幕闪烁、抖动问题解决
文件--选项-->高级-->显示-->勾选禁用硬件图像加速
- ubuntu20.04虚拟机无法自动获取IP地址
具体操作 # ens33 为网卡名称 sudo dhclient ens33
- Day 13 13.2 requests之请求参数与请求体
请求参数与请求体参数 一.什么是params参数(请求参数) get 方法是可以向服务器发送信息的,除了可以请求需要的页面之外,也可以发送我们指定的内容,这就是通过 params 参数实现的 requ ...
- DRF全局总结
基础部分 一.创建工程 1.创建虚拟环境 python -m venv 路径 2.安装Django 进入虚拟环境 pip install Django 3.创建项目 django-admin star ...
- [学习计划]mysql常用语句-随学随整理
<> 不等于 三元表达式 select *, if (num=1, "第一", "其他") as 别名 from 表 COUNT 统计总数并按某 ...
- Svn Linux 启动
svnserve -r -d /svn 后面是svn 安装目录
- 无法识别为 cmdlet、函数、脚本文件或可运行程序的名称。请检查名称的拼写,如果包括路径,请确保路径正确,然后再试一次
无法识别为 cmdlet.函数.脚本文件或可运行程序的名称.请检查名称的拼写,如果包括路径,请确保路径正确,然后再试一次 解决方法: 1.在开始菜单里找到Windows PowerShell.并以管理 ...
- Xrdp服务安装配置实现Linux远程桌面访问以及问题处理
0x00 基础介绍 0x01 安装桌面环境 Ubuntu 系列 0x02 Xrdp 安装使用 How to Install xrdp on Ubuntu ? How to Install xrdp t ...
- CentOS 7安装配置vsftp并搭建FTP(一)
vsftp-VSFTP是一个基于GPL发布的类Unix系统上使用的FTP服务器软件.关于这个软件的详细信息 大家可以自行百度. 以上自己安装vsftp系统环境 二.查看自己的服务器是否安装了vsftp ...
- springboot docker打包镜像
首先在idea中创建springboot项目,pom文件packaging 为jar ,然后编写接口. 编写Dockerfile 注意Dockerfile只能这样命名. 使用maven打包命令或者使用 ...