【问题标题】:Why RDD calculating count take so much time为什么 RDD 计算计数需要这么多时间
【发布时间】:2019-07-15 03:52:55
【问题描述】:

(英语不是我的母语,如有错误请见谅)

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

hive 表大约有 300 万列,可能序列化成本很高。我检查了 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(_))

【问题讨论】:

    标签: apache-spark apache-spark-sql


    【解决方案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()
    

    【讨论】:

      【解决方案2】:

      您的第一种方式是将所有数据加载到 spark、网络、序列化和转换操作中,这将花费大量时间。

      第二种方式,我想是因为他省略了hive层。

      如果你只是count,第三种方式比较好,就是执行count后只加载count结果

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多