迭代/流式传输Spark Dataframe的最佳方法

时间:2016-03-14 16:50:04

标签: apache-spark spark-dataframe

我有一个Spark作业,它读取一个镶有大约150.000.000个键/值条目的镶木地板文件。

    SparkConf conf = new SparkConf();
    conf.setAppName("Job");
    JavaSparkContext jsc = new JavaSparkContext(conf);
    SQLContext sql = new SQLContext(jsc);
    DataFrame df = sql.read().parquet(path);

我的目标是将键/值对写入HBase,但是我遇到堆内存问题,我怀疑这不是最好的方法。我想将计算推送到集群,但我无法弄清楚如何跳过收集部分。现在我的代码看起来像这样:

HBaseClient client = HbaseWrapper.initClient();
   df.collectAsList().stream().forEach(row -> {
            try {
                HbaseWrapper.putRows(client, row);
            } catch (Exception e) {
                e.printStackTrace();
            }
        });
   jsc.stop();

我试图在没有流媒体的情况下首先收集列表,然后将其写下来,但这也需要永远。

任何见解都表示赞赏。

1 个答案:

答案 0 :(得分:2)

您收到OOM错误,因为collectAsList会将所有数据发送给驱动程序。

要解决此问题,您可以使用foreachPartitions,因此您将并行流式传输到Hbase。

    df.toJavaRDD().foreachPartition(new VoidFunction<Iterator<Row>>() {

        @Override
        public void call(Iterator<Row> t) throws Exception {
            try {
                HBaseClient client = HbaseWrapper.initClient();
                while(t.hasNext()){
                    Row row = t.next();
                    HbaseWrapper.putRows(client, row);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }

        }
    });