我们的应用程序使用长时间运行的spark上下文(就像spark RPEL一样),使用户能够在线执行任务。我们大量使用spark广播来处理维度数据。在通常的实践中,我们广播维度表,并使用数据帧API将事实表与其他维度表连接起来。其中一个维度表相当大,内存中有大约100k条记录和15MB的大小(kyro序列化只少了几个MB)。
我们看到,去规范化数据帧上的每一个spark JOB都会导致所有维度被一遍又一遍地广播。大一点的桌子每次播放大约需要7秒。我们正试图找到一种方法,使维度表在每个上下文生命周期内只广播一次。我们尝试了sqlcontext和sparkcontext广播。
除了星火广播,还有其他选择吗?或者有没有办法减少数据帧的内存占用(压缩/序列化等)-post-kyro仍然是15MB:()?
可能的替代
我们使用Iginite-spark集成在工作开始时加载大量数据,并根据需要不断变化。
在嵌入式模式下,您可以在Spark上下文启动时启动点火,并在最后终止。
你可以在这里阅读更多关于它的信息。
https://ignite.apache.org/features/igniterdd.html
最后,我们能够找到一个权宜之计,直到在后续版本中激发对RDD的支持。显然,即使在v2.1.0中也没有解决这个问题。
该解决方案依赖于RDD映射分区,下面是方法的简要总结
- 收集维度表记录作为键值对的映射,并使用spark上下文进行广播。您可以使用RDD.keyBy
- 使用RDD mapPartitions方法映射事实行。对于每个事实行映射奇偶校验
- 收集事实行中的维度id并查找维度记录
- 通过对事实中的维度id进行反规范化,生成一个新的事实行表