并行框架2:PySpark之RDD(基于Python)

RDD简介

  RDD(Resilient Distributed Dataset)叫做弹性分布式数据集,是 Spark 中最基本的数据抽象,它代表一个不可变、可分区、里面的元素可并行计算的集合。RDD 具有数据流模型的特点:自动容错、位置感知性调度和可伸缩性。RDD 允许用户在执行多个查询时显式地将工作集缓存在内存中,后续的查询能够重用工作集,这极大地提升了查询速度。

RDD属性

  • 一组分片(Partition),即数据集的基本组成单位。对于 RDD 来说,每个分片都会被一个计算任务处理,并决定并行计算的粒度。用户可以在创建 RDD 时指定 RDD 的分片个数,如果没有指定,那么就会采用默认值。默认值就是程序所分配到的 CPU Core 的数目。

  • 一个计算每个分区的函数。Spark 中 RDD 的计算是以分片为单位的,每个 RDD 都会实现 compute 函数以达到这个目的。compute 函数会对迭代器进行复合,不需要保存每次计算的结果。

  • RDD 之间的依赖关系。RDD 的每次转换都会生成一个新的 RDD,所以 RDD 之间就会形成类似于流水线一样的前后依赖关系。在部分分区数据丢失时,Spark可以通过这个依赖关系重新计算丢失的分区数据,而不是对 RDD 的所有分区进行重新计算。

  • 一个 Partitioner,即 RDD 的分片函数。当前 Spark 中实现了两种类型的分片函数,一个是基于哈希的 HashPartitioner,另外一个是基于范围的RangePartitioner。只有对于于 key-value 的 RDD,才会有Partitioner,非 key-value 的 RDD 的 Parititioner 的值是 None。Partitioner 函数不但决定了RDD本身的分片数量,也决定了 parent RDD Shuffle 输出时的分片数量。

  • 一个列表,存储存取每个 Partition 的优先位置(preferred location)。对于一个 HDFS 文件来说,这个列表保存的就是每个 Partition 所在的块的位置。按照“移动数据不如移动计算”的理念,Spark 在进行任务调度的时候,会尽可能地将计算任务分配到其所要处理数据块的存储位置。

RDD在Python的API

创建RDD

参考资料1

from pyspark import SparkContext
sc = SparkContext("local", "Simple App")

加载数据

  • 通过并行集合导入:
rdd = sc.parallelize([('a',7),('a',2),('b',2)])
rdd2 = sc.parallelize([('a',2),('d',1),('b',1)])
rdd3 = sc.parallelize(range(10))
rdd4 = sc.parallelize([('a',['x','y','z']),
                       ('b',['p','r'])])
  • 导入外部数据:
    • 从本地或 HDFS 读取一个文本文件:textFile
    • 读取一个文件的路径:wholeTextFiles
textFile = sc.textFile("my/directory/*.txt")
textFile2 = sc.wholeTextFiles("my/directory/")

获取RDD信息

基本信息
  • 列出 RDD 分区数:
rdd.getNumPartitions()

返回值默认是 2,如果在导入并行集合数据时标明分区,例如:

rdd = sc.parallelize([('a',7),('a',2),('b',2)], 3)

getNumPartitions 函数返回的值即为设定值 3.

  • 计算 RDD 样本个数:
rdd.count()

返回值为 3.

  • 通过 key 计算 RDD 样本个数:
rdd.countByKey()

RDD 的元素若是一个 tuple 形式 (a,b) 存在,则 a 为 key,b 为 value.

上述代码返回值为一个 dictionary 格式:

defaultdict(<type 'int'>, {
   'a': 2, 'b': 1})

通过 items() 可以得到 list 返回格式,list 中每个元素为 (key, count) 的 tuple 的形式:

rdd.countByKey().items()

上述代码返回值为:

[('a', 2), ('b', 1)]
  • 通过 Value 计算 RDD 样本个数:
rdd.countByValue()

上述代码返回值为:

defaultdict(<type 'int'>, {
   ('b', 2): 1, ('a', 2): 1, ('a', 7): 1})

⚠️:这边按照 countByValue() 中的 value 不是指按照 tuple 中的 value 来计数,而是把整个 tuple 当作一个 value 来统计计数。

  • 返回一个 key-values 数对给主机:
rdd.collectAsMap()
{
   'a': 2, 'b': 2}

这边有点难以解释 'a': 2 ,如果将 rdd 改成:

rdd = sc.parallelize([('a',2),('a',7),('b',2)])
rdd.collectAsMap()

上述代码返回值为:

{
   'a': 7, 'b': 2}

从以上两个结果可以看出,collectAsMap() 返回的是 key 对应的 value 是 RDD 里最新的一个值(譬如说,rdd = sc.parallelize([('a',2),('a',7),('b',2)]) 中的 ‘a’ 一开始指代的是 2,然后又被 7 覆盖,因此 ‘a’ 最终指的是 7)。

  • RDD的元素求和:
rdd3.sum()

上述代码返回值为:

4950
  • 判断RDD是否为空:

例如:

rdd.isEmpty()
<
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值