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

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')

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

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

【讨论】:

以上是关于为数十亿个不同的键优化分区的主要内容,如果未能解决你的问题,请参考以下文章

Neo4j 如何创建数十亿个节点?

在 MongoDB 中快速搜索数十亿个小文档的策略

在 Java 中使用并发在磁盘上创建键值存储

kafka主题分区的数量和数据中不同键的数量

面试官:如何在十亿个单词字典中,判断某个单词是否存在?(布隆过滤器)

为数十亿台设备提供权限自动重置功能