Spark是否支持使用Parquet文件进行分区修剪

时间:2016-05-12 07:28:00

标签: apache-spark amazon-s3 hive parquet

我正在处理一个大型数据集,该数据集由两列分隔 - plant_nametag_id。第二个分区 - tag_id有200000个唯一值,我主要通过特定tag_id值访问数据。如果我使用以下Spark命令:

sqlContext.setConf("spark.sql.hive.metastorePartitionPruning", "true")
sqlContext.setConf("spark.sql.parquet.filterPushdown", "true")
val df = sqlContext.sql("select * from tag_data where plant_name='PLANT01' and tag_id='1000'")

我希望快速响应,因为这会解析为单个分区。在Hive和Presto中,这需要几秒钟,但在Spark中它运行了几个小时。

实际数据保存在S3存储桶中,当我提交sql查询时,Spark关闭并首先获取Hive Metastore中的所有分区(其中200000个),然后调用refresh()强制S3对象库中所有这些文件的完整状态列表(实际调用listLeafFilesInParallel)。

这两个操作是如此昂贵,是否有任何设置可以让Spark更早地修剪分区 - 在调用元数据存储期间,还是之后立即?

3 个答案:

答案 0 :(得分:2)

是的,spark支持分区修剪。

Spark会执行分区目录列表(顺序或并行listLeafFilesInParallel),以便第一次构建所有分区的缓存。同一应用程序中的查询,扫描数据利用此缓存。所以你看到的缓慢可能是因为这个缓存构建。扫描数据的后续查询使用缓存来修剪分区。

这些是显示用于填充缓存的分区的日志。

App > 16/11/14 10:45:24 main INFO ParquetRelation: Listing s3://test-bucket/test_parquet_pruning/month=2015-01 on driver
App > 16/11/14 10:45:24 main INFO ParquetRelation: Listing s3://test-bucket/test_parquet_pruning/month=2015-02 on driver
App > 16/11/14 10:45:24 main INFO ParquetRelation: Listing s3://test-bucket/test_parquet_pruning/month=2015-03 on driver

这些是显示正在修剪的日志。

App > 16/11/10 12:29:16 main INFO DataSourceStrategy: Selected 1 partitions out of 20, pruned 95.0% partitions.

convertToParquetRelation中提及getHiveQlPartitionsHiveMetastoreCatalog.scala

答案 1 :(得分:0)

只是一个想法:

HadoopFsRelation的Spark API文档说, (https://spark.apache.org/docs/1.6.2/api/java/org/apache/spark/sql/sources/HadoopFsRelation.html

  

“...从存储在文件中的Hive样式分区表中读取时   系统,它能够从路径中发现分区信息   输入目录,并在启动之前执行分区修剪   阅读数据......“

所以,我猜“listLeafFilesInParallel”不是问题。

类似的问题已经在spark jira:https://issues.apache.org/jira/browse/SPARK-10673

尽管“spark.sql.hive.verifyPartitionPath”设置为false,并且对性能没有影响,我怀疑 问题可能是由未注册的分区引起的。请列出表格的分区并验证是否全部 分区已注册。否则,请恢复您的分区,如以下链接所示:

Hive doesn't read partitioned parquet files generated by Spark

更新

  1. 我想在编写数据时设置了合适的镶木地板块大小和页面大小。

  2. 使用动态分区方法创建一个带有分区的新hive表,并将文件格式设置为镶木地板,从非分区表中加载它。 (https://cwiki.apache.org/confluence/display/Hive/DynamicPartitions) 运行一个简单的配置单元查询,然后运行一个spark程序进行比较。

  3. 免责声明:我不是火花/镶木地板专家。这个问题听起来很有意思,因此做出了回应。

答案 2 :(得分:0)

最近在这里弹出类似的问题: http://apache-spark-user-list.1001560.n3.nabble.com/Spark-SQL-reads-all-leaf-directories-on-a-partitioned-Hive-table-td35997.html#a36007

这个问题很旧,但我也想在这里发布解决方案。

spark.sql.hive.convertMetastoreParquet=false

将使用Hive镶木地板Serde代替Spark内置镶木地板Serde。 Hive的Parquet Serde不会在所有分区上执行listLeafFiles,而是仅直接从所选分区中读取。在具有许多分区和文件的表上,这要快得多(也更便宜)。随意尝试哦! :)