我正在尝试使用Spark在集群上处理csv文件。我想了解是否需要在每个工作程序节点上显式读取文件以并行进行处理,还是驱动程序节点将读取文件并将数据分布到整个群集中以进行内部处理? (我正在使用Spark 2.3.2和Python)
我知道可以使用SparkContext.parallelize()对RDD进行并行化,但是对于Spark DataFrames呢?
if __name__=="__main__":
spark=SparkSession.builder.appName('myApp').getOrCreate()
df=spark.read.csv('dataFile.csv',header=True)
df=df.filter("date>'2010-12-01' AND date<='2010-12-02' AND town=='Madrid'")
因此,如果我在群集上运行上述代码,整个操作将由驱动程序节点完成还是将df分布到群集上,并且每个工作进程都在其数据分区上执行处理?
答案 0 :(得分:1)
严格地说,如果运行上面的代码,它将不会读取或处理任何数据。 DataFrames基本上是在RDD之上实现的抽象。与RDD一样,您必须区分转换和动作。由于您的代码仅包含一个filter(...)
转换,因此将在readind或数据处理方面进行记录。 Spark只会创建作为执行计划的DataFrame。您必须执行count()
或write.csv(...)
之类的操作才能实际触发CSV文件的处理。
如果执行此操作,则1..n个工作程序节点将读取并处理数据。驱动程序节点永远不会读取或处理它。在您的代码中,实际涉及多少个或工作节点取决于源文件中分区的数量。一个工作节点可以并行处理源文件的每个分区。在您的示例中,它可能是单个CSV文件,因此在读取文件后调用df.rdd.getNumPartitions()
时,它应返回1
。因此,只有一个工作节点将读取数据。如果您在filter(...)
操作之后检查分区数,情况也是如此。
有两种方法可以并行处理单个CSV文件:
您可以通过调用df.repartition(n)
与要拥有的分区数n
来手动重新划分源DataFrame。但是-这是很重要的-这意味着所有数据都有可能通过网络发送(也称为随机播放)!
您可以在DataFrame上执行聚合或联接。这些操作必须触发随机播放。然后,Spark使用spark.sql.shuffle.partitions
(默认值:200)中指定的分区数对结果DataFrame进行分区。