关于为什么shuffle写入数据的详细说明比apache spark

时间:2016-03-29 10:41:02

标签: apache-spark hdfs cloudera

enter image description here

  1. 任何人都可以向我详细说明在火花UI中指定输入,输出,随机读取和随机写入的内容是什么?
  2. 另外,有人可以解释这项工作的输入是如何写入的25~30%? 根据我的理解,shuffle write是无法在内存中保存的临时数据和在聚合或减少期间需要发送给其他执行程序的数据的总和。
  3. 以下代码:

    hiveContext.sql("SELECT * FROM TABLE_NAME WHERE PARTITION_KEY = 'PARTITION_VALUE'")
        .rdd
        .map{case (row:Row)
                =>((row.getString(0), row.getString(12)),
                    (row.getTimestamp(11), row.getTimestamp(11),
                        row))}
        .filter{case((client, hash),(d1,d2,obj)) => (d1 !=null && d2 !=null)}
       .reduceByKey{
           case(x, y)=>
                if(x._1.before(y._1)){
                    if(x._2.after(y._2))
                        (x)
                    else
                        (x._1, y._2, y._3)
                }else{
                    if(x._2.after(y._2))
                        (y._1, x._2, x._3)
                    else
                        (y)
                }
       }.count()
    

    其中ReadDailyFileDataObject是一个case行,它将行字段保存为容器。 容器是必需的,因为有30列,超过22的元组限制。

    更新了代码,删除了案例类,因为我看到同样的问题,当我使用Row本身而不是案例类时。

    现在我看到了

      

    任务:10/7772

         

    输入:2.1 GB

         

    随机写:14.6 GB

    如果有帮助,我正在尝试处理存储为镶木地板文件的表,包含210亿行。

    以下是我正在使用的参数

    "spark.yarn.am.memory" -> "10G"
    "spark.yarn.am.cores"  -> "5"
    "spark.driver.cores"   -> "5"
    "spark.executor.cores" -> "10"
    "spark.dynamicAllocation.enabled" -> "true"
    "spark.yarn.containerLauncherMaxThreads" -> "120"
    "spark.executor.memory" -> "30g"
    "spark.driver.memory" -> "10g"
    "spark.driver.maxResultSize" -> "9g"
    "spark.serializer" -> "org.apache.spark.serializer.KryoSerializer"
    "spark.kryoserializer.buffer" -> "10m"
    "spark.kryoserializer.buffer.max" -> "2001m"
    "spark.akka.frameSize" -> "2020"
    

    SparkContext注册为

    new SparkContext("yarn-client", SPARK_SCALA_APP_NAME, sparkConf)
    

    在纱线上,我看到了

      

    分配的CPU VCores:95

         

    分配的内存:309 GB

         

    运行容器:10

2 个答案:

答案 0 :(得分:1)

实际上很难在没有代码的情况下提供答案,但您可能会多次浏览数据,因此您处理的总音量实际上是原始数据的“X”倍。

您可以发布正在运行的代码吗?

修改

查看代码,之前我遇到过这种问题,这是由于Row的序列化,所以这也可能是你的情况。

什么是“ReadDailyFileDataObject”?它是一个类,一个案例类吗?

我会先尝试运行你的代码:

hiveContext.sql("SELECT * FROM TABLE_NAME WHERE PARTITION_KEY = 'PARTITION_VALUE'")
    .rdd
    .map{case (row:Row)
            =>((row.get(0).asInstanceOf[String], row.get(12).asInstanceOf[String]),
                (row.get(11).asInstanceOf[Timestamp], row.get(11).asInstanceOf[Timestamp]))}
    .filter{case((client, hash),(d1,d2)) => (d1 !=null && d2 !=null)}
   .reduceByKey{
       case(x, y)=>
            if(x._1.before(y._1)){
                if(x._2.after(y._2))
                    (x)
                else
                    (x._1, y._2)
            }else{
                if(x._2.after(y._2))
                    (y._1, x._2)
                else
                    (y)
            }
   }.count()

如果这样可以解决你的改组问题,那么你可以稍微重构一下: - 如果还没有,请将其设为案例类。 - 创建它像“ReadDailyFileDataObject(row.getInt(0),row.getString(1)等...)”

希望这可以作为答案,并帮助您找到瓶颈。

答案 1 :(得分:1)

将鼠标悬停在Input Output Shuffle Read Shuffle Write上时显示的提示可以很好地解释:

  

INPUT:从Hadoop或Spark存储中读取的字节和记录。

     

OUTPUT:写入Hadoop的字节和记录。

     

SHUFFLE_WRITE:写入磁盘的字节和记录,以便将来在随机播放中读取。

     

Shuffle_READ:读取的总洗牌字节数和记录数(包括本地读取的数据和从远程执行器读取的数据)。

在您的情况下,150.1GB占所有1409完成任务的输入大小(即从目前为止从HDFS读取的总大小),874GB占所有1409完成任务在节点的本地磁盘上写入。

您可以参考What is the purpose of shuffling and sorting phase in the reducer in Map Reduce Programming?了解整体随机播放功能。