RDD操作
- 创建RDD
- 两种创建方式
- parallelize() 方法
lines = sc.parallelize(["pandas", "i like pandas"])
- 外部读取数据创建RDD
lines = sc.textFile("/path/to/README.md")
- 两种创建方式
- RDD操作
-
转化操作
-
返回新的RDD
-
针对各个元素的转换操作
- 实现map()转化操作
nums = sc.parallelize([1, 2, 3, 4]) squared = nums.map(lambda x: x * x).collect() for num in squared: print "%i " % (num)
- 实现flatMap()转化操作
lines = sc.parallelize(["hello world", "hi"]) words = lines.flatMap(lambda line: line.split(" ")) words.first() # 返回"hello" # platMap实现由一个输入元素生成多个输出元素 lines = sc.parallelize(["hello world", "hi"]) words = lines.map(lambda line: line.split(" ")) words.first() # 返回"['hello', 'word']"
- 实现filter()转化操作
inputRDD = sc.text.File("log.txt") errorsRDD = inputRDD.filter(lambda x:"error" in x)
-实现union()转化操作
errorsRDD = inputRDD.filter(lambda x: "error" in x) warningsRDD = inputRDD.filter(lambda x: "warning" in x) badLinesRDD = errorsRDD.union(wariningsRDD)
-
伪集合操作
- 实现union()操作 返回两个RDD中所有元素
与数学中的union()操作不同的是,如果输入的RDD中有重复数据,Spark的union()操作也会包含这些重复数据(如有必要,我们可以通过distinct() 实现相同的效果)。
- 实现distinct()操作 去除两个RDD中重复的元素
- 实现inersection()操作 只返回两个RDD重并都有的元素
- 实现subtract()操作 返回一个由只存在于第一个RDD中而不存在于第二个RDD 中的所有元素组成的RDD
- 实现cartesian()操作 计算两个RDD的笛卡儿积
-
-
行动操作
- reduce()操作 接收一个函数作为参数,这个函数要操作两个RDD的元素类型的数据并返回一个同样类型的新元素。
sum = rdd.reduce(lambda x,y : x+y)
- fold(zero)()操作
sum = rdd.fold(1,(lambda x,y : x+y))
- aggregate()操作
rdd = sc.parallelize([1, 2, 3]) sumCount = rdd1.aggregate((0,0),(lambda acc, value: (acc[0] + value, acc[1]+1)), (lambda acc1, acc2:(acc1[0] + acc2[0], acc1[1] + acc2[1]))) print( sumCount[0] / float(sumCount[1]))
- take(n)操作
- top()操作 会使用数据的默认顺序
- foreach()操作 对RDD 中的每个元素使用给定的函数
- 利用count()进行计数
print "Input had " + badLinsRDD.count() + " concerning lines" print "Here are 10 examples:" for line in badLinesRDD.take(10): print line
- collect()函数
RDD 还有一个collect() 函数,可以用来获取整个RDD 中的数据。如果你的程序把RDD筛选到一个很小的规模,并且你想在本地处理这些数据时,就可以使用它。记住,只有当你的整个数据集能在单台机器的内存中放得下时,才能使用collect(),因此,collect() 不能用在大规模数据集上。向驱动器返回结果。触发实际计算。
-
向Spark传递函数
word = rdd.filter(lambda s : "error" in s)
def containsError(s):
return "error" in s
word = rdd.filter(containsError)
持久化(缓存)
- 优势:
- 避免对此重计算,造成格外大的开销;
- 如果一个有持久化数据的节点发生故障,Spark会在需要用到缓存的数据时重算丢失的数据分区。
- cache() 是persist()的简化方式,调用persist的无参版本,也就是调用persist(StorageLevel.MEMORY_ONLY),cache只有一个默认的缓存级别MEMORY_ONLY,即将数据持久化到内存中。
- persist() 可以通过传递一个 StorageLevel 对象来设置缓存的存储级别。
- 持久化级别
持久化级别 | 说明 |
---|---|
MEMORY_ONLY | 将RDD以非序列化的Java对象存储在JVM中。如果没有足够的内存存储RDD,则某些分区将不会被缓存,每次需要时都会重新计算。这是默认级别。 |
MEMORY_AND_DISK | 将RDD以非序列化的Java对象存储在JVM中。如果数据在内存中放不下,则溢写到磁盘上.需要时则会从磁盘上读取 |
MEMORY_ONLY_\SER (Java and Scala) | 将RDD以序列化的Java对象(每个分区一个字节数组)的方式存储.这通常比非序列化对象(deserialized objects)更具空间效率,特别是在使用快速序列化的情况下,但是这种方式读取数据会消耗更多的CPU。 |
MEMORY_AND_DISK_SER (Java and Scala) | 与MEMORY_ONLY_SER类似,但如果数据在内存中放不下,则溢写到磁盘上,而不是每次需要重新计算它们。 |
DISK_ONLY | 将RDD分区存储在磁盘上。 |
MEMORY_ONLY_2, MEMORY_AND_DISK_2等 | 与上面的储存级别相同,只不过将持久化数据存为两份,备份每个分区存储在两个集群节点上。 |
内容来自《Spark快速大数据分析》
"持久化级别"引自:https://blog.youkuaiyun.com/sunnyyoona/article/details/73348202