(英语不是我的母语,所以请原谅任何错误)
我使用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(_))
答案 0 :(得分:1)
您的第一种方法是查询数据,而不是获取数据。很大的不同。
val sql = s"SELECT * FROM xxxtable"
val hiveData = sqlContext.sql(sql).rdd
我们可以以程序员的身份查看上面的代码,并认为“是的,这就是我们抓取所有数据的方式”。但是,获取数据的方式是通过查询而不是从文件中读取数据。基本上,将发生以下步骤:
那里有很多步骤!比以下情况更重要:
val inputPath = s"/path/to/above/hivetable"
val hdfsData = sc.textFile(inputPath)
在这里,我们只有一步:
看,那是步骤的1/3。尽管这是一个简单的查询,但要使其进入该RDD仍需要大量开销和处理。一旦将其放入RDD中,处理将变得更加容易。如您的代码所示:
val count = hdfsData.count()
答案 1 :(得分:0)
第一种方法是将所有数据加载到火花,网络,序列化和转换操作将花费大量时间。
第二种方式,我认为是因为他省略了蜂巢层。
如果您只是count
,则第三种方法更好,它是在执行count之后仅加载计数结果