二级域名网站优化百度快速收录教程
目录
RDD 的内部工作机制
创建 RDDs
Schema
从文件中读取
弹性分布式数据集(RDDs)是一种分布式的不可变 JVM 对象集合,它允许你非常快速地执行计算,并且它们是 Apache Spark 的支柱。
顾名思义,数据集是分布式的;它根据某个键被分割成块,并分布到执行器节点。这样做允许对这些数据集进行非常快速的计算。同样,“理解 Spark”中提到的,RDDs 跟踪(记录)应用于每个块的所有转换,以加快计算速度,并在出现问题并且那部分数据丢失时提供回退;在这种情况下,RDDs 可以重新计算数据。这种数据血统是防止数据丢失的另一道防线,是数据复制的补充。
涵盖的主题有:
- RDD 的内部工作机制
- 创建 RDDs
- 全局作用域与局部作用域
- 转换(Transformations)
- 动作(Actions)
RDD 的内部工作机制
RDDs 并行运行。这是在 Spark 中工作的最大优势:每个转换都并行执行,从而大幅提高速度。
对数据集的转换是懒执行的。这意味着任何转换只有在对数据集调用动作时才执行。这有助于 Spark 优化执行。例如,考虑分析师通常会对数据集进行的以下非常常见的步骤:
1. 统计某个列中不同值的出现次数。
2. 选择以 A 开头的那些值。
3. 将结果打印到屏幕上。
正如前面提到的步骤听起来很简单,但如果只对以字母 A 开头的项目感兴趣,那么统计所有其他项目的不重复值就没有意义。因此,Spark 可以只统计以 A 开头的项目,然后打印结果到屏幕上。
让我们用代码来分解这个例子。首先,我们使用 .map(lambda v: (v, 1)) 方法命令 Spark 映射 A 的值,然后选择以 'A' 开头的记录(使用 .filter(lambda val: val.startswith('A')) 方法)。
如果我们调用 .reduceByKey(operator.add) 方法,它将减少数据集并添加(在这个例子中,计数)每个键的出现次数。所有这些步骤都转换了数据集。
其次,我们调用 .collect() 方法来执行步骤。这一步是我们数据集上的动作 - 它最终统计了数据集的不同元素。实际上,动作可能会颠倒转换的顺序,在映射之前先过滤数据,从而在传递给 reducer 之前得到一个更小的数据集。
创建 RDDs
在 PySpark 中创建 RDD 有两种方式:你可以使用 .parallelize(...) 并行化一个集合(列表或某些元素的数组):
data = sc.parallelize([('Amber', 22), ('Alfred', 23), ('Skye',4), ('Albert', 12), ('Amber', 9)])
或者你可以引用一个文件(或文件)位于本地或外部某处:
data_from_file = sc.\ textFile('/Users/drabast/Documents/PySpark_Data/VS14MORT.txt.gz',4)
sc.textFile(..., n) 中的最后一个参数指定了数据集被分成的分区数。
Spark 可以读取多种文件系统:本地的如 NTFS、FAT 或 Mac OS Extended (HFS+),或者分布式文件系统如 HDFS、S3、Cassandra 等。
支持多种数据格式:文本、parquet、JSON、Hive 表,以及使用 JDBC 驱动程序的数据从关系数据库中读取。请注意,Spark 可以自动处理压缩数据集(如我们前面例子中的 Gzipped 数据集)。
根据数据的读取方式,持有它的对象将略有不同。从文件中读取的数据表示为 MapPartitionsRDD 而不是 ParallelCollectionRDD,当我们 .parallelize(...) 一个集合。
Schema
RDDs 是无模式的数据结构(与 DataFrames 不同,我们将在下一章讨论)。因此,当使用 RDDs 时,Spark 允许像下面代码片段那样并行化数据集:
data_heterogenous = sc.parallelize([('Ferrari', 'fast'),{'Porsche': 100000},['Spain','visited', 4504]
]).collect()
所以,我们可以混合使用几乎任何东西:一个元组、一个字典或一个列表,Spark 都不会抱怨。
一旦你对数据集调用了 .collect()(也就是说,执行一个动作将其带回驱动程序),你可以像在 Python 中通常那样访问对象中的数据:
data_heterogenous[1]['Porsche']
这将产生以下结果:
100000
.collect() 方法将 RDD 的所有元素作为列表序列化后返回到驱动程序。
从文件中读取
当你从文本文件中读取时,文件中的每一行都会形成一个 RDD 的元素。
data_from_file.take(1) 命令将产生以下(有些难以阅读的)输出:
为了使其更易于阅读,让我们创建一个元素列表,以便每行都表示为值的列表。