Apache Spark在reducer端使用map of key和源数据,而不是groupByKey()



在回顾这个问题时,我发现我有类似的需求,但是在更大的数据集上。好消息是,每个组的数据将适合reducer侧的内存。

我需要对每组的数据做一些处理,并把结果写出来。有多个分组值

输入(复制自那个问题):

{"key1": "1", "key1": "2", "key1": "3", "key2": "55", "key2": "66"}

输出(复制自那个问题):

{"key1": ["1","2","3"], "key2": ["55","66"]}

由于这是非常低效的,迫使大量的数据移动,我在想如果我可以使用spark框架仅仅映射不同的键到不同的reducer,并让reducer端源数据(从数据库或其他),并做它的计算。

在这种情况下,我将使用Spark来分散工作负载,而不是其他。这是一种有用的方法吗?还有其他选择吗?

这取决于数据源;在很多方面,groupBy逻辑所做的工作与关系数据库在构建索引或查询时所做的工作是一样的。

记录的完全打乱在spark和hadoop中最常见的原因是,通常这些系统用于处理数据不适合在预处理中被很好地组织的情况,要么是因为数据太大,要么是因为它以无序的形式到达(如来自许多不同服务器源的日志文件),在那里它不经常被访问,不足以证明连续预处理。

所以一般来说,如果你的源数据已经有效地按照你需要的分组进行了组织,要么是因为分组键是数据库源的主键,要么是因为它们已经在源文件中以这种方式进行了分组,那么你确实可以通过只在reducer中拉入记录值来做得更好,因为你的存储格式已经有效地执行了shuffle操作。

然而如果数据不是已经被你的分组关键字或者分散在未排序的文件,它将总体是低效的试图把关键数据的还原剂,因为每次你想获取所有数据的一个关键,底层存储层或读者必须扫描完整的数据集可能包含那些钥匙,有效的数据访问的数量乘以数量的钥匙。

即使数据有索引,如果记录值需要额外的磁盘来访问它,那么支付额外的数据洗牌成本仍然是值得的,因为顺序磁盘访问可以获得比随机访问高几个数量级的吞吐量。

主要的收获是,数据洗牌被优化为能够在或多或少的一次传递中组织数据分组,而按键过滤是多传递的,除非有效地索引。因此shuffle成本是源存储层成本的权衡。

最新更新