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算子 ...
随机推荐
- ElasticSearch 实现分词全文检索 - 概述
需求 做一个类似百度的全文搜索功能 所用的技术如下: ElasticSearch Kibana 管理界面 IK Analysis 分词器 SpringBoot ElasticSearch 简介 ES ...
- java学习日记20230226-java环境搭建及运行机制
JDK安装 配置环境变量: 当执行的程序在当前目录不存在时,windows去系统path环境变量里面进行查找,如果没有找到报错不存在该命令. 我的电脑-属性-高级系统设置--环境变量 增加JAVA_H ...
- 图论专题 - LibreOJ
第三部分 图论 第 1 章 最小生成树 #10064 「一本通 3.1 例 1」黑暗城堡#10065 「一本通 3.1 例 2」北极通讯网络 #10066 「一本通 3.1 练习 1」新的开始#100 ...
- 【剑指Offer】【树】二叉搜索树的后序遍历序列
题目:输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果.如果是则输出Yes,否则输出No.假设输入的数组的任意两个数字都互不相同. A:在二叉树的后序遍历中,数组最后一个元素为根节点,左 ...
- Ubuntu docker安装、验证、卸载
卸载Docker CE 卸载Docker CE软件包: sudo apt-get purge docker-ce 主机上的图像,容器,卷或自定义配置文件不会自动删除.要删除所有图像,容器和卷: sud ...
- vue常用插件集合(常用,但一般UI库又不太能满足)
# v-base-plugins ``` bash # install npm i v-base-plugins --save npm start #引入 import myPlugin fr ...
- C++ 中的匿名函数(lambda表达式)
问题引入 使用std::sort函数对自定义类型排序时,我们需要传入一个比较函数作为参数.该比较函数只需要使用一次,但占有一个全局命名域中的名字,而且非常短,短到不需要名字就知道它的作用.这很浪费命名 ...
- 【面试题】 webpack面试篇
1.与webpack类似的工具还有哪些?谈谈你为什么选择webpack? grunt 优点:出现的比较早,第一代打包工具 缺点:配置项太多,只有一个配置文件,而且不同的插件可能有自己的配置字段,学习成 ...
- 查询redis路径,清除redis缓存
查询redis路径 1.执行ps -ef | grep redis 命令,结果如下(记住PID) 2.执行ps -u 系统用户名,进一步确定进程id, 我这里的系统用户名是root,执行ps -u r ...
- 压力&负载理论
一.定义: 1.压力测试 是给软件不断加压,强制其在极限的情况下运行,观察它可以运行到何种程度,从而发现性能缺陷,是通过搭建与实际环境相似的测试环境,通过测试程序在同一时间内或某一段时间内,向 ...