为什么RDD计算计数需要这么多时间

时间:2019-07-15 03:52:55

标签: apache-spark apache-spark-sql

(英语不是我的母语,所以请原谅任何错误)

我使用SparkSQL从蜂巢表中读取4.7TB数据,并执行计数操作。大约需要1.6个小时。直接从HDFS txt文件读取并执行计数时,仅需10分钟。这两个作业使用相同的资源和并行度。为什么RDD计数需要这么多时间?

配置单元表具有约30万列,并且序列化可能会很昂贵。我检查了Spark UI,每个任务读取了约240MB数据,大约需要3.6分钟来执行。我不敢相信序列化的开销如此之大。

从蜂巢中读取(耗时1.6个小时):

val sql = s"SELECT * FROM xxxtable"
val hiveData = sqlContext.sql(sql).rdd
val count = hiveData.count()

从hdfs读取(需要10分钟):

val inputPath = s"/path/to/above/hivetable"
val hdfsData = sc.textFile(inputPath)
val count = hdfsData.count()

使用SQL计数时,仍然需要5分钟:

val sql = s"SELECT COUNT(*) FROM xxxtable"
val hiveData = sqlContext.sql(sql).rdd
hiveData.foreach(println(_))

2 个答案:

答案 0 :(得分:1)

您的第一种方法是查询数据,而不是获取数据。很大的不同。

val sql = s"SELECT * FROM xxxtable"
val hiveData = sqlContext.sql(sql).rdd

我们可以以程序员的身份查看上面的代码,并认为“是的,这就是我们抓取所有数据的方式”。但是,获取数据的方式是通过查询而不是从文件中读取数据。基本上,将发生以下步骤:

  • 从文件读取到临时存储区
  • 查询引擎处理有关临时存储的查询并创建结果
  • 将结果读入RDD

那里有很多步骤!比以下情况更重要:

val inputPath = s"/path/to/above/hivetable"
val hdfsData = sc.textFile(inputPath)

在这里,我们只有一步:

  • 从文件读取到RDD

看,那是步骤的1/3。尽管这是一个简单的查询,但要使其进入该RDD仍需要大量开销和处理。一旦将其放入RDD中,处理将变得更加容易。如您的代码所示:

val count = hdfsData.count()

答案 1 :(得分:0)

第一种方法是将所有数据加载到火花,网络,序列化和转换操作将花费大量时间。

第二种方式,我认为是因为他省略了蜂巢层。

如果您只是count,则第三种方法更好,它是在执行count之后仅加载计数结果