假设我们有一个parquet文件(或其他任何文件)p,它有一些列和行。文件P有一个列a,只有0或1。此外,列A为0的行仅占该文件的1%。我们想读取列A为0的行
最简单的方法是全部读取并使用where
将A过滤为1。这种方法花费a太多,因为我们实际上只需要文件P的1%,我们不能在读取P之前将P写入两个文件,其中a为0,a为1。如果你不把它读入内存,这看起来是不可能的,你怎么过滤它呢?
如果我们让文件p在写入磁盘之前按列A排序,我们可以在文件p的前一部分将A设为0。在这种情况下,Spark是否可以读取A为0的行?
这将取决于您正在谈论的文件格式,以及文件分区的方式。让我们讨论一下拼花文件:
分区列过滤
如果你的文件被这样写:
df.write.partitionBy("A").parquet(filename)
这是最好的情况。您的文件将以spark.read.parquet(filename).filter(col("A") === 0)
只读取所需数据的方式写入。这是可能的原因是因为parquet文件对A
列的每个值都有一个子目录。因此完全有可能不读取A == 1
.
对非分区列进行过滤
这是你使用的文件格式有影响的地方。在parquet文件的情况下,也有一些过滤被下推到读取文件。
拼花文件被分成行组。对于每个行组,parquet文件保留一些元数据(包括该行组的最小/最大值)。这允许跳过行组(假设您只想读取A == 0
和最小值为1
的值,您可以跳过整个行组)。
对于CSV文件,例如,第二个是不可能的。