如何在 Spark 中更高效地加载 Parquet 文件 (pySpark v1.2.0)

How to More Efficiently Load Parquet Files in Spark (pySpark v1.2.0)

我正在加载高维镶木地板文件,但只需要几列。我当前的代码如下:

dat = sqc.parquetFile(path) \
          .filter(lambda r: len(r.a)>0) \
          .map(lambda r: (r.a, r.b, r.c))

我对正在发生的事情的心理模型是加载所有数据,然后丢弃我不想要的列。我显然宁愿它甚至不阅读这些专栏,而且根据我对镶木地板的了解,这似乎是可能的。

所以有两个问题:

  1. 是我的心智模型错了吗?或者 spark 编译器是否足够聪明,只读取上面示例中的 a、b 和 c 列?
  2. 如何强制sqc.parquetFile()更有效地读入数据?

Spark 总是以懒惰的方式做事,使用原生的 scala 功能。 scala 代码已经编译,它使运行时智能,我的意思是懒惰,决定。对于镶木地板,它应该只读取代码引用的必要数据。当然,这取决于特定镶木地板文件的结构。关键是它将利用柱状格式。我对Python的了解还不够,不过应该可以做到同样的事情。也许检查 pyspark Row class 是否使用了某种懒惰的魔法。一种快速验证的方法是进行受控实验,编写另一个引用更多字段但不输出它们的 rdd 操作。然后你可以只比较两个操作之间的挂钟时间差。根据底层 parquet 文件的一些相关细节,即使它进行了延迟加载,您也可能看不到差异。

你应该使用 Spark DataFrame API:https://spark.apache.org/docs/1.3.0/sql-programming-guide.html#dataframe-operations

类似于

dat.select("a", "b", "c").filter(lambda r: len(r.a)>0)

或者您可以使用 Spark SQL:

dat.regiserTempTable("dat")
sqc.sql("select a, b, c from dat where length(a) > 0")

是的,它只会从磁盘中选择字段。

" 打开所有数据文件,但只读取每个文件中包含该列值的部分。列值连续存储,从而最大限度地减少处理单个列中的值所需的 I/O ."

此文档适用于 impala,我认为 spark 的阅读逻辑也相同 http://www.cloudera.com/documentation/archive/impala/2-x/2-1-x/topics/impala_parquet.html#parquet_data_files_unique_1