如何在spark中启用分区修剪

swa*_*ghi 9 pruning apache-spark apache-spark-sql spark-dataframe

我正在阅读镶木地板数据,我看到它列出了驱动程序端的所有目录

Listing s3://xxxx/defloc/warehouse/products_parquet_151/month=2016-01 on driver
Listing s3://xxxx/defloc/warehouse/products_parquet_151/month=2014-12 on driver
Run Code Online (Sandbox Code Playgroud)

我在where子句中指定了month = 2014-12.我尝试过使用spark sql和数据框架API,看起来两者都没有修剪分区.

使用Dataframe API

df.filter("month='2014-12'").show()
Run Code Online (Sandbox Code Playgroud)

使用Spark SQL

sqlContext.sql("select name, price from products_parquet_151 where month = '2014-12'")
Run Code Online (Sandbox Code Playgroud)

我在版本1.5.1,1.6.1和2.0.0上尝试了上述内容

MrC*_*ine 3

Spark需要首先在驱动程序中加载分区元数据才能知道分区是否存在。Spark在扫描数据的过程中会查询目录来查找现有的分区,以了解是否可以修剪分区。

我已经在 Spark 2.0 上对此进行了测试,您可以在日志消息中看到。

16/10/14 17:23:37 TRACE ListingFileCatalog: Listing s3a://mybucket/reddit_year on driver
16/10/14 17:23:37 TRACE ListingFileCatalog: Listing s3a://mybucket/reddit_year/year=2007 on driver
Run Code Online (Sandbox Code Playgroud)

这并不意味着我们要扫描每个分区中的文件,但 Spark 将存储分区的位置以供将来在表上查询。

您可以看到它实际上在分区过滤器中传递以修剪数据的日志:

16/10/14 17:23:48 TRACE ListingFileCatalog: Partition spec: PartitionSpec(StructType(StructField(year,IntegerType,true)),ArrayBuffer(PartitionDirectory([2012],s3a://mybucket/reddit_year/year=2012), PartitionDirectory([2010],s3a://mybucket/reddit_year/year=2010), ...PartitionDirectory([2015],s3a://mybucket/reddit_year/year=2015), PartitionDirectory([2011],s3a://mybucket/reddit_year/year=2011)))
16/10/14 17:23:48 INFO ListingFileCatalog: Selected 1 partitions out of 9, pruned 88.88888888888889% partitions.
Run Code Online (Sandbox Code Playgroud)

explain(True)如果您对查询 运行,您可以在逻辑计划中看到这一点:spark.sql("select created_utc, score, name from reddit where year = '2014'").explain(True)

这将向您显示计划,您可以看到它正在计划底部进行过滤:

+- *BatchedScan parquet [created_utc#58,name#65,score#69L,year#74] Format: ParquetFormat, InputPaths: s3a://mybucket/reddit_year, PartitionFilters: [isnotnull(year#74), (cast(year#74 as double) = 2014.0)], PushedFilters: [], ReadSchema: struct<created_utc:string,name:string,score:bigint>
Run Code Online (Sandbox Code Playgroud)