Spark在单个任务中执行了太多分区,而不是分发它。
我们正在从HBase吸收大量数据到Spark数据集中。
由于不兼容,我们无法使用HBase-Spark,并已将基本的JavaAPI客户端用于HBase。
为帮助并行化从HBase提取数据,我们将“ startRows”放入数据集中,对数据集重新分区以提供16个分区,每个分区包含4个开始行。
然后我们使用mapPartitions()查询4个开始行,并返回实际行数据的迭代器。
这确实会导致所有行都被提取,但是即使我们确定数据在这些起始行之间是均匀分布的,Spark仍坚持将大多数分区移至3或4个执行程序,而不是16。
我相当确定这是因为Spark不了解我们正在加载的实际数据,并且正在优化数据集中startRows上的灵魂。
反正有强制每个分区将火花作为一个任务,一个执行程序来执行这些操作吗?
List<String> keys = new ArrayList<>();
for(int salt=0; salt<maxSalt; salt++) { // maxSalt=64
keys.add( extractStartRow( mainKey, String.valueOf(salt));
}
Dataset<String> saltSeed = sparkSession.createDataset(keys,
Encoders.STRING());
int partitions = 16;
saltRange = saltRange.repartition(partitions);
Dataset<Results> = saltRange.mapPartitions(new Ingestor(mainKey), Encoders.bean(Results.class));
// Ingestor function, does the actual read from Hbase for the given salted start row.
我们想找到一种方法,让更多的任务/执行者在 从HBase读取的问题。无论我们尝试什么,Spark都会将工作量减少到只有几个执行程序。其余的没有分区,也没有数据可摄取。活跃的执行者需要几个小时。