为数十亿个不同的键优化分区
Posted
技术标签:
【中文标题】为数十亿个不同的键优化分区【英文标题】:Optimize Partitionning for billions of distinct keys 【发布时间】:2019-05-10 11:09:07 【问题描述】:我每天都在使用 PySpark 处理一个文件,以获取有关设备通过网络导航的信息。在每个月底,我想使用窗口功能来为每个设备进行导航。这是一个非常缓慢的处理,即使有很多节点,所以我正在寻找加快它的方法。
我的想法是对数据进行分区,但我有 20 亿个不同的键,所以 partitionBy
似乎不合适。即使bucketBy
也可能不是一个好的选择,因为我每天都会创建n
存储桶,因此不会附加文件,但每天都会创建x 个文件。
有人有解决办法吗?
所以这里是每天导出的示例(在每个 parquet 文件中,我们找到 9 个分区):
这是我们在每个月初启动的 partitionBy 查询(compute_visit_number 和 compute_session_number 是我在笔记本上创建的两个 udf):
【问题讨论】:
您能否添加一些示例数据和您尝试过且需要优化的代码?这将有助于我们了解您想要做什么。 我添加了更多截图和示例 【参考方案1】:您要确保每个设备的数据都在同一个分区中,以防止在执行窗口功能时发生交换。或者至少尽量减少数据所在的分区数。
为此,我将在您写入数据时创建一个名为 partitionKey 的列 - 其中包含 mc_device 列上的 mod - 您修改的数字是您想要的分区数。基于将运行月末查询的集群大小的这个数字。 (如果 mc_device 不是整数,则先创建校验和)。
如果仍然需要,您可以在日期列上创建辅助分区。
您的月末查询应该改变:
w = Windows.partitionBy('partitionKey', 'mc_device').orderBy(event_time')
如果您将日期保留为辅助分区列,则仅将数据帧重新分区为 partitionKey:
df = df.repartition('partitionKey')
此时,每个设备的数据都将在同一个分区中,不需要进行任何交换。排序应该更快,并且您的查询有望在合理的时间内完成。
如果仍然很慢,则在写入数据时需要更多分区。
【讨论】:
以上是关于为数十亿个不同的键优化分区的主要内容,如果未能解决你的问题,请参考以下文章