优化数十亿个不同键的分区

时间:2019-05-10 11:09:07

标签: apache-spark pyspark apache-spark-sql databricks azure-databricks

我每天都在使用PySpark处理文件,以收集有关通过网络进行设备导航的信息。在每个月的月底,我想使用窗口功能以获取每个设备的导航历程。即使有很多节点,这也是一个非常缓慢的处理过程,因此我正在寻找加速它的方法。

我的想法是对数据进行分区,但是我有20亿个不同的键,因此partitionBy似乎不合适。甚至bucketBy也不是一个好选择,因为我每天都会创建n存储桶,因此不会附加文件,但是每天都会创建文件的x部分。

有人可以解决吗?

这是每天导出的示例(在每个实木复合地板文件中,我们发现9个分区):

enter image description here

这是我们在每个月的开始时启动的partitionBy查询(compute_visit_number和compute_session_number是我在笔记本上创建的两个udf): enter image description here

1 个答案:

答案 0 :(得分:0)

您要确保每个设备数据都在同一分区中,以防止在执行窗口功能时进行交换。或者至少将数据可能位于的分区数量最小化。

要执行此操作,我将在写入数据时创建一个名为partitionKey的列-该列包含mc_device列上的mod-其中mod的编号是所需的分区数。基于该数字的群集大小将运行月末查询。 (如果mc_device不是整数,请先创建一个校验和。)

如果仍然需要,可以在日期列上创建辅助分区。

您的月末查询应更改:

w = Windows.partitionBy('partitionKey', 'mc_device').orderBy(event_time')

如果将日期保留为第二分区列,则将数据框重新分区为仅partitionKey:

df = df.repartition('partitionKey')

这时,每个设备的数据将位于同一分区中,不需要进行任何交换。排序应该更快,并且您的查询有望在合理的时间内完成。

如果仍然很慢,则在写入数据时需要更多分区。