Apache spark 在DataFrame上使用union()/coalesce(1,false)时,为什么Spark中会出现大量数据混乱?

Apache spark 在DataFrame上使用union()/coalesce(1,false)时,为什么Spark中会出现大量数据混乱?,apache-spark,apache-spark-sql,rdd,shuffle,Apache Spark,Apache Spark Sql,Rdd,Shuffle,我有一个Spark作业,它对ORC数据进行一些处理,并使用Spark 1.4.0中引入的DataFrameWriter save()API存储ORC数据。我有下面的一段代码,它使用了重洗牌内存。如何优化下面的代码?有什么问题吗?正如预期的那样,它工作正常,只是由于GC暂停和洗牌大量数据而导致速度缓慢,因此会出现内存问题。我是新手 JavaRDD<Row> updatedDsqlRDD = orderedFrame.toJavaRDD().coalesce(1, false).map(

我有一个Spark作业,它对ORC数据进行一些处理,并使用Spark 1.4.0中引入的DataFrameWriter save()API存储ORC数据。我有下面的一段代码,它使用了重洗牌内存。如何优化下面的代码?有什么问题吗?正如预期的那样,它工作正常,只是由于GC暂停和洗牌大量数据而导致速度缓慢,因此会出现内存问题。我是新手

JavaRDD<Row> updatedDsqlRDD = orderedFrame.toJavaRDD().coalesce(1, false).map(new Function<Row, Row>() {
   @Override
   public Row call(Row row) throws Exception {
        List<Object> rowAsList;
        Row row1 = null;
        if (row != null) {
          rowAsList = iterate(JavaConversions.seqAsJavaList(row.toSeq()));
          row1 = RowFactory.create(rowAsList.toArray());
        }
        return row1;
   }
}).union(modifiedRDD);
DataFrame updatedDataFrame = hiveContext.createDataFrame(updatedDsqlRDD,renamedSourceFrame.schema());
updatedDataFrame.write().mode(SaveMode.Append).format("orc").partitionBy("entity", "date").save("baseTable");

将RDD或数据帧合并到单个分区意味着所有处理都在一台机器上进行。由于各种原因,这不是一件好事:所有的数据都必须在网络上进行洗牌,没有更多的并行性,等等。相反,除了将数据合并到一台机器之外,您应该考虑其他操作符,如reduceByKey、mapPartitions,或者其他几乎所有的操作


注意:看看你的代码我不明白你为什么要把它放到一台机器上,您可能只需要删除该部分。

Hi Holden感谢我有一个复杂的用例,它迫使我连续处理一个分区,因为如果我不使用coalesce,行的顺序处理会很严格。多台机器的数据顺序不同,我的结果也不正确。上面的代码工作得很好,只是没有扩展它。顺便说一句,我使用的是coalesce(1,false)shuffle false,但它为什么要执行shuffling?shuffle false只意味着它不支持增加分区的数量(从scaladoc:但是,如果您执行的是剧烈的合并,例如,使numPartitions=1,这可能会导致您的计算在比您喜欢的更少的节点上进行(例如,在numPartitions=1的情况下为一个节点)。为了避免这种情况,您可以传递shuffle=true。这将添加一个shuffle步骤,但意味着当前上游分区将并行执行(无论当前分区是什么)也就是说,使用shuffle=true实际上可能会获得更好的性能。如果您确实需要一次处理一个分区,您可能会更好地查看ToLocalWriter中的代码(以及缓存)(注意:不要实际使用ToLocalWriter,只需查看其实现即可)然后构造代码,对一个分区使用mapPartitionsWithIndex和filter,然后在循环中使用foreach执行该操作。这将允许您避免将数据带回单个节点,而这可能是问题的一大根源。最后请注意,要提高性能,最好的办法是找到放松你的限制,这样你就不需要一行一行地处理了。祝你好运!你好,霍尔顿,非常感谢。我将尝试合并(1,正确)其余我无法更改的内容,因为基于序列列逐行进行串行处理。就像你说的合并(1,正确)应该可以更好地工作并保持我的结果正确让我试试。嗨@Holden我已经按照你的建议更改了代码,请参见问题中的编辑,但仍然无法解决洗牌和OOM问题
JavaRDD<Row> indexedRdd = sourceRdd.cache().mapPartitionsWithIndex(new Function2<Integer, Iterator<Row>, Iterator<Row>>() {
            @Override
            public Iterator<Row> call(Integer ind, Iterator<Row> rowIterator) throws Exception {
                List<Row> rowList = new ArrayList<>();

                while (rowIterator.hasNext()) {
                    Row row = rowIterator.next();
                    List<Object> rowAsList = iterate(JavaConversions.seqAsJavaList(row.toSeq()));
                    Row updatedRow = RowFactory.create(rowAsList.toArray());
                    rowList.add(updatedRow);
                }           
                return rowList.iterator();
            }
        }, true).coalesce(200,true);