Spark读取分区-资源成本分析

时间:2019-07-17 10:34:59

标签: performance apache-spark partitioning

在读取Spark中按列spark.read.json("/A=1/B=2/C=3/D=4/E=5/")进行分区的数据时,将仅扫描文件夹E = 5中的文件。

但是,假设我有兴趣通过所有数据源读取其中C = my_value的分区。指令将为spark.read.json("/*/*/C=my_value/")

在引擎盖下描述的场景中,计算发生了什么? Spark只会列出A和B的分区值吗?还是也会扫描所有叶子(实际文件)?

1 个答案:

答案 0 :(得分:2)

感谢您提出一个有趣的问题。 Apache Spark使用Hadoop的FileSystem抽象来处理通配符模式。在源代码中,它们被称为全局模式

org.apache.hadoop.fs.FileSystem#globStatus(org.apache.hadoop.fs.Path)方法用于返回“与路径模式匹配的路径数组”。然后,此函数调用org.apache.hadoop.fs.Globber#glob来为glob模式找出确切的文件匹配算法。 org.apache.spark.sql.execution.datasources.DataSource#checkAndGlobPathIfNecessary调用globStatus。您可以添加一些断点以了解其在后台的工作方式。

但长话短说:

  

在引擎盖下描述的场景中,计算发生了什么? Spark只会列出A和B的分区值吗?还是也会扫描所有叶子(实际文件)?

Spark会将您的glob分成3个部分[“ *”,“ *”,“ C = my_value”]。稍后,它将使用Hadoop org.apache.hadoop.fs.FileSystem#listStatus(org.apache.hadoop.fs.Path)方法列出每个级别的文件。对于每个文件,它将建立一个路径,并尝试将其与当前模式匹配。当算法寻找“ C = my_value”时,匹配文件将保留为“候选”,仅在最后一步被过滤掉。

除非您有很多文件,否则此操作不会对您造成伤害。也许这就是为什么您宁愿保留较少但较大的文件的原因之一(著名的数据工程问题是“过多的小文件”)。