多级分区表的Spark(EMR)分区修剪行为

如果我有一个用多层分区创建的表,即由两列(州,城市)组成,如下所示:

    state=CA,city=Anaheim
    state=Texas,city=Houston
    state=Texas,city=Dallas
    state=Texas,city=Austin
    state=CA,city=SanDiego

如果我运行像这样的选择查询:

select * from table_name where city=Houston

即在使用了第二个分区列的位置,它将仅扫描city=Houston中的state=Texas分区吗?我非常确定,Hive的运行方式却非常希望确认Spark中的行为。另外,如果在EMR的Spark中执行该行为,会有所不同吗?

sdadaadfaaf 回答:多级分区表的Spark(EMR)分区修剪行为

如果您使用配置单元来存储表,那么肯定可以对外部和内部分区进行分区修剪。 Hive单独保留有关表的分区信息的元数据。因此,当查询针对特定分区时,它可以进行优化。

您实际上可以使用explain select * from table_name where city ='Houston';

测试此行为

但是,如果您使用Spark来以嵌套结构写入分区,那么我不太确定。如果查询需要遍历整个目录结构,那么当目录数量巨大时,这将是昂贵的。

,

让我们从从文件路径加载数据而不是从元存储开始。在这种情况下,Spark首先将执行一个递归文件列表,以发现嵌套的分区文件夹及其中的文件。然后将分区文件夹定义为用于分区修剪的字段。因此,在您对任何分区列进行过滤的情况下,Spark只会选择满足该谓词的分区。您可以通过对查询使用explain方法来进行确认。请注意以下PartitionCount: 1

scala> input1.where("city = 'Houston'").explain()
== Physical Plan ==
*(1) FileScan parquet [id#32,state#33,city#34] Batched: true,Format: Parquet,Location: InMemoryFileIndex[file:/tmp/data],PartitionCount: 1,PartitionFilters: [isnotnull(city#34),(city#34 = Houston)],PushedFilters: [],ReadSchema: struct<id:int>

将其与没有任何过滤器的查询计划进行比较,其中PartitionCount: 5

scala> input1.explain()
== Physical Plan ==
*(1) FileScan parquet [id#55,state#56,city#57] Batched: true,PartitionCount: 5,PartitionFilters: [],ReadSchema: struct<id:int>

现在,第二种情况是加载分区表时。在这种情况下,分区由Hive管理,因此可以节省昂贵的递归文件列表。当您在分区列上进行过滤时,Spark将再次仅选择相关的分区。请注意以下explain计划:

scala> input2.where("city = 'Houston'").explain()
== Physical Plan ==
*(1) FileScan parquet default.data[id#39,state#40,city#41] Batched: true,Location: PrunedInMemoryFileIndex[file:/tmp/data/state=Texas/city=Houston],PartitionFilters: [isnotnull(city#41),(city#41 = Houston)],ReadSchema: struct<id:int>
本文链接:https://www.f2er.com/3119752.html

大家都在问