使用大量输入文件来加快InMemoryFileIndex的Spark SQL作业

时间:2018-11-02 00:30:07

标签: apache-spark apache-spark-sql

我有一个用Java编码的apache spark sql作业(使用数据集),得到的输入是70,000至150,000个文件。

构建InMemoryFileIndex似乎需要45分钟到1.5个小时。

这段时间没有日志,网络使用率非常低,几乎没有CPU使用率。

以下是我在标准输出中看到的示例:

24698 [main] INFO org.spark_project.jetty.server.handler.ContextHandler  - Started o.s.j.s.ServletContextHandler@32ec9c90{/static/sql,null,AVAILABLE,@Spark}
25467 [main] INFO org.apache.spark.sql.execution.streaming.state.StateStoreCoordinatorRef  - Registered StateStoreCoordinator endpoint
2922000 [main] INFO org.apache.spark.sql.execution.datasources.InMemoryFileIndex  - Listing leaf files and directories in parallel under: <a LOT of file url's...>
2922435 [main] INFO org.apache.spark.SparkContext  - Starting job: textFile at SomeClass.java:103

在这种情况下,有45分钟的时间基本上没有任何反应(据我所知)。

我使用以下文件加载文件

sparkSession.read().textFile(pathsArray)

有人可以解释InMemoryFileIndex中发生了什么,如何使这一步更快?

1 个答案:

答案 0 :(得分:0)

InMemoryFileIndex负责分区发现(并因此对分区进行修剪),它正在列出文件,并且如果您有很多文件,它可能会运行并行作业,这可能会花费一些时间,因为它必须索引每个文件。这样做时,Spark会收集有关文件的一些基本信息(例如,文件的大小),以计算一些基本统计信息,这些统计信息将在查询计划期间使用。如果您希望每次读入数据时都避免这种情况,可以使用metastore和saveAsTable()命令将数据另存为数据源表(Spark 2.1支持),并且此分区发现将仅执行一次,然后信息将保存在metastore中。然后您可以使用metastore读取数据

sparkSession.read.table(table_name)

,它应该很快,因为将跳过此分区发现阶段。我建议看this Spark Summit讨论该问题的话题。