在Java中使用Spark数据帧进行大数据聚合

时间:2018-08-20 18:46:05

标签: java apache-spark dataframe apache-spark-sql phoenix

在具有5个分区的分片表中,每个数据大约有6-8TB。该表在HBase中。我建立了一个基于Java的spark作业,该作业从该表中读取数据并执行一些聚合以获取一组被视为键的列的聚合,然后最终将结果写回到另一个表中。最初,我尝试使用Spark Map和foreach api,并使用HashMap这样的数据结构在内存中执行聚合。最终使用jdbc连接将其上载到表中。但是,性能确实很差,工作从未完成。然后,使用DataFrames编写了一个新作业。我使用HBaseRDD API提取数据并将其转换为数据帧,然后执行groupBY和聚合,最后使用

保存结果

“ finalDF.save(” org.apache.phoenix.spark“,SaveMode.Overwrite,output_conf);”

这也很花时间,所以我根据关键范围划分了任务,并一次处理了一个范围(例如100万用户),并在2001年之前对数据进行了重新分区以确保高度压缩。

DataFrame sessionDF = new PhoenixRDD(sqlContext.sparkContext(),inputTable,JavaConverters.asScalaBufferConverter(cols).asScala().toSeq(),Option.apply(filter),Option.apply(source),hconf).toDataFrame(sqlContext).repartition(partitions);

使用的火花作业属性如下:

--spark.app.name test
--spark.master yarn
--spark.deploy.mode cluster
--spark.driver.cores 2
--spark.driver.memory 4G
--spark.executor.instances 8
--spark.executor.cores 2
--spark.executor.memory 16G
--spark.executor.heartbeatInterval 6000000
--spark.default.parallelism 2001
--spark.yarn.executor.memoryOverhead 4096
--spark.yarn.scheduler.heartbeat.interval-ms 6000000
--spark.network.timeout 6000000
--spark.serializer org.apache.spark.serializer.KryoSerializer
--spark.shuffle.io.retryWait 60s
--spark.shuffle.io.maxRetries 10

问题在于,此作业大约需要8到10个小时来处理一百万个用户,接近1TB的数据,此后通常会开始提供“ org.apache.spark.shuffle.MetadataFetchFailedException:缺少输出位置洗牌1英寸,再花5-6个小时即可完成。我尝试增加执行程序和内存,但在运行过程中仍然遇到此问题,并且难以处理全部数据。

有人可以建议我如何改善这项工作的处理能力吗? 如果您需要任何进一步的信息,请告诉我。

这是汇总步骤的简化版本:

finalDF
    .select(col("OID"), col("CID")
        , col(“P”))
    .groupBy(col("OID")
        , col("CID”))
    .agg(sum(when(col("P").equalTo(lit("sd")).or(col("P").equalTo(lit("hd"))), lit(1)).otherwise(lit(0))).alias("P"));

作为该语句的一部分,还有更多字段和其他聚合。

0 个答案:

没有答案