Spark RDD基础(一)

spark对数据的核心抽象—弹性分布式数据集(Resilient Distributed Dataset)即RDD,RDD是一个不可变的分布式对象集合,每个RDD被分为多个分区。
在spark中,对数据的所有操作不外乎创建RDD,转化已有RDD以及调用RDD操作进行求值

RDD基础

#创建RDD
lines=sc.textFile("README.md")
#转化操作由一个RDD生成一个新的RDD
#返回一个只存储包含python字符串的新RDD
pythonLines=lines.filter(lambda line:"Python" in line)
#行动操作
pythonLines.first()

转化操作和行动操作的区别在于spark计算RDD的方式不用。spark只有第一次在一个行动操作中用到时才会真正的计算。比如对于上面的例子,spark在运行

lines=sc.textFile("README.md")

时候并不会立刻读取文件并存储,而是当spark了解整个操作链后,只计算真正要用的数据,对于这个例子spark在行动操作first()中,spark只需要扫描文件直到找到第一个匹配的行为止,而不需要读取整个文件。

在实际操作中我们经常使用persist把数据读取到内存中,并反复查询这部分数据。比如,如果我们想多次对README文件中包含python的行进行计算,可以写如下的脚本

#将RDD持久化到内存中
pythonLines.persist
pythonLines.count()
pythonLines.first()

每个spark程序无外乎都是下面的流程

1.从外部数据创建输入RDD
2.使用诸如filter()这样的操作对RDD进行转化,定义新的RDD
3.告诉spark对需要被重用的中间RDD执行persisit()操作
4.使用行动操作(count(),first())触发一次并行计算,spark并不会立马执行,而是优化后再执行

创建RDD

#parallelize方法将集合转化为rdd
lines = sc.parallelize(["pandas", "i like pandas"])

#textFile方法
lines=sc.textFile("README.md")

RDD操作

spark支持两种操作转化操作,行动操作

转化操作
转化操作执行时返回新的RDD的操作,转化出来的RDD是惰性求值的,只有在行动中用到这些RDD时才会被计算,许多转化操作只会操作RDD中的一个元素,并不是所有的转化操作都是这样

比如提取日志文件的错误信息

inputRDD=sc.testFile("log.txt")
errorsRDD=inputRDD.filter(lambda x:"error" in x)
warningsRDD = inputRDD.filter(lambda x: "warning" in x)
badLinesRDD = errorsRDD.union(warningsRDD)

通过转化操作,从已有的RDD中派生新的RDD,spark会使用谱系图记录这些RDD的依赖关系,spark在需要用这些信息的时候按需计算每个RDD,也可以依靠谱系图在丢失数据的情况下恢复丢失的数据

行动操作
行动操作需要实际的输出,它会强制执行哪些求值必须用到的RDD转化操作
示例:对badLinesRDD进行计数操作,并且打印前十条记录

print "Input had " + badLinesRDD.count() + " concerning lines"
for line in badLinesRDD.take(10):
    print line

这里使用了take()取出少量的数据集,也可以使用collect()函数获取整个RDD中的数据,但是使用collect需要注意内存是否够用。如果数据集特别大的时候,我们需要把数据写到诸如HDFS之类的分布式存储系统,当调用一个新的行动操作的时候整个RDD会从头计算,我们要将中间结果持久化

惰性求值

spark类似sc.textFile()或者转化操作都是惰性的,可以使用一个行动操作来强制spark执行RDD转化操作

函数传递

#使用lambda方法传递
word = rdd.filter(lambda s: "error" in s)

#定义一个函数然后传递
def containsError(s):
    return "error" in s
word = rdd.filter(containsError)

传递函数时要小心,python会在不经意间把函数所在的对象也序列化传出,有时如果传递的类里包含了python不知道如何序列化输出的对象,也可能导致程序失败。

如下是一个错误的函数传递示例

class SearchFunctions(object):
    def __init__(self, query):
        self.query = query
    def isMatch(self, s):
        return self.query in s
    def getMatchesFunctionReference(self, rdd):
        # 问题:在"self.isMatch"中引用了整个self
        return rdd.filter(self.isMatch)
    def getMatchesMemberReference(self, rdd):
        # 问题:在"self.query"中引用了整个self
        return rdd.filter(lambda x: self.query in x)

对于上述的方法替代方案如下

class WordFunctions(object):
    def getMatchesNoReference(self, rdd):
        # 安全:只把需要的字段提取到局部变量中
        query = self.query
        return rdd.filter(lambda x: query in x)
                                            spark快速大数据分析学习笔记
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值