我正在加载高维镶木地板文件,但只需要几列。我当前的代码如下所示:
dat = sqc.parquetFile(path)
.filter(lambda r: len(r.a)>0)
.map(lambda r: (r.a, r.b, r.c))
我对正在发生的事情的心理模型是,它加载所有数据,然后扔掉我不想要的列。我显然希望它甚至不阅读这些专栏中的内容,从我对镶木地板的理解来看,这似乎是可能的。
所以有两个问题:
- 我的心智模型错了吗?或者 Spark 编译器是否足够智能,只能在上面示例中读取 a、b 和 c 列?
- 如何强制
sqc.parquetFile()
更高效地读取数据?
你应该使用 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")
Spark 总是以懒惰的方式做事,使用原生的 scala 功能。scala代码已经编译好了,它使运行时变得聪明,我的意思是懒惰,决策。对于镶木地板,它应该只读取代码引用的必要数据。当然,这取决于特定镶木地板文件的结构。关键是它将利用列式格式。我对Python还不够了解,但它应该能够做同样的事情。也许检查一下 pyspark Row 类是否使用了某种懒惰的魔法。一种快速验证的方法是进行受控实验,编写另一个引用更多字段但不输出字段的 rdd 操作。然后,您可以比较2个操作之间的挂钟时间差。根据基础 parquet 文件的某些相关详细信息,即使它执行延迟加载,您也可能看不到差异。
是的,它只会从磁盘中选择字段。
"打开所有数据文件,但仅读取包含该列值的每个文件的部分。列值是连续存储的,最大限度地减少了处理单个列中的值所需的 I/O。
这个文档是针对黑斑羚的,我认为阅读逻辑对于火花也是一样的 http://www.cloudera.com/documentation/archive/impala/2-x/2-1-x/topics/impala_parquet.html#parquet_data_files_unique_1