在不读取整行数据的情况下对分区列执行Spark SQL



只对分区列执行Spark SQL查询的情况经常出现。例如,假设您希望以编程方式从表中获取最新的date(其中date是分区列(。从概念上讲,你可以这样做:

val myData = spark.table("chrisa.my_table")
val latestDate = myData.select($"date").distinct
.orderBy($"date".desc)
.limit(1).collect

我假设"date"是一个可以排序的列,也许它是一个由"YYYYmmDD"格式化的字符串,比如20220908

有时我看到类似的代码非常慢,即它清楚地读取底层文件数据,有时我看到它几乎是即时的,即可能只访问关于分区列的表元数据,而不读取文件。

问题是:在什么条件下,它不必读取底层的整行数据?具体而言,

  • 存储格式或元数据的真实性是什么
  • 哪些转换将允许在不读取整行数据的情况下进行此操作

我使用的是Spark 2.4.2

经过进一步的挖掘,我发现这两个JIRA准确地回答了我的问题。

  • https://issues.apache.org/jira/browse/SPARK-12890
  • https://issues.apache.org/jira/browse/SPARK-34194

似乎第一个JIRA被关闭而支持第二个,因为它更好地描述了问题。

这两个文件的总结似乎是,曾经有一个配置参数spark.sql.optimizer.metadataOnly用于允许我想要做的事情,但如果底层文件没有行,这可能会导致不正确的结果。因此,参数和整个概念被弃用并删除,以支持正确性而非速度。

甚至我在原文章中的例子也显示了一个案例,如果底层文件数据没有行,它可能会给出两个不同的结果:

val myData = spark.table("chrisa.my_table")
val latestDate = myData.select($"date").distinct
.orderBy($"date".desc)
.limit(1).collect

例如,如果存在元数据的最新日期没有行,则完全扫描将产生下一个最新日期(实际上有行(,但仅元数据版本将产生具有元数据的最晚日期。

最新更新