我发现我编写的pyspark脚本存在一些可伸缩性问题,并且想知道是否有人能够轻松解决这些问题。
我的用例与此处提供的用例非常相似:
Separate multi line record with start and end delimiter
因为我有一些多行数据,其中记录之间有逻辑分隔符。例如。数据看起来像:
AA123
BB123
CCXYZ
AA321
BB321
CCZYX
...
使用上一个答案中的示例,我使用像...这样的脚本将其分成多个记录。
spark = SparkSession \
.builder \
.appName("TimetableSession") \
#Played around with setting the available memory at runtime
.config("spark.executor.memory", "8g") \
.config("spark.driver.memory", "8g") \
.getOrCreate()
files = os.path.join("data","*_lots_of_gzipped_files.gz")
df=spark.sparkContext.textFile(files).toDF()
df=df.withColumn("id", monotonically_increasing_id())
w=Window.partitionBy().orderBy('id')
df=df.withColumn('AA_indicator', expr("case when entry like 'AA%' then 1 else 0 end"))
#!!!Blowing up with OOM errors here at scale!!!
df=df.withColumn('index', sum('AA_indicator').over(w))
df.show()
+--------------------+---+------------+-----+
| entry| id|AA_indicator|index|
+--------------------+---+------------+-----+
| AA123| 1| 1| 1|
| BB123| 2| 0| 1|
| CCXYZ| 3| 0| 1|
| AA321| 4| 1| 2|
| BB321| 5| 0| 2|
| CCZYX| 6| 0| 2|
+--------------------+---+------------+-----+
当我将其扩展到>时,这似乎适用于合理大小的数据(例如50MB的数据)。 1GB的数据我看到了Java OOM错误。即使在尝试分配>时,我也遇到了同样的问题。 20GB内存到spark.driver / executor。
我认为问题是数据分区的窗口和所有内容都被立即收集到内存而不是被分类?但是我可能会对此不以为然。
我使用jupyter pyspark notebook https://github.com/jupyter/docker-stacks/tree/master/pyspark-notebook在独立的docker容器中运行此脚本。
对于更好地编制“记录”索引方法或如何更好地解决问题的任何帮助都将非常感激。
答案 0 :(得分:1)
可能是因为您使用的窗口没有PARTITION BY
:
Window.partitionBy().orderBy('id')
在这种情况下,Spark不会按顺序分发数据并处理单台机器上的所有记录。
拥有大量gzipped
文件会使情况更糟,因为无法拆分gzip压缩。因此每个文件都加载到一台机器上,也可以加载OOM。
总的来说,这不是让Spark受益的原因。
使用较低级别的代码替换窗口的累积和,如How to compute cumulative sum using Spark
中所示这似乎也很相关:Avoid performance impact of a single partition mode in Spark window functions