spark(emr)分区剪枝行为

pes8fvy9  于 2021-06-25  发布在  Hive
关注(0)|答案(2)|浏览(471)

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

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

如果我运行这样的select查询:

select * from table_name where city=Houston

i、 在第二个分区列已经被使用的地方,它会扫描第二个分区列吗 city=Houston 分区 state=Texas ? 我很确定Hive是如何运作的,但我很想确认spark的行为。另外,如果在emr的spark中执行,行为会有什么不同吗?

wfauudbj

wfauudbj1#

如果您使用配置单元来存储表,那么它肯定能够对外部分区和内部分区进行分区修剪。hive单独保存关于表的分区信息的元数据。因此,当查询针对特定分区时,它能够进行优化。
你可以使用 explain select * from table_name where city ='Houston'; 但是,如果您使用spark在嵌套结构中编写分区,那么我不太确定。如果查询需要遍历整个目录结构,那么当目录数量很大时,这将是非常昂贵的。

iklwldmw

iklwldmw2#

让我们从从从文件路径加载数据开始,而不是从元存储加载数据。在本例中,spark将首先执行递归文件列表,以发现嵌套分区文件夹及其内的文件。然后将分区文件夹定义为用于分区修剪的字段。因此,在您的情况下,当您对任何分区列进行筛选时,spark将只选择满足该 predicate 的分区。您可以使用 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, Format: Parquet, Location: InMemoryFileIndex[file:/tmp/data], PartitionCount: 5, PartitionFilters: [], PushedFilters: [], ReadSchema: struct<id:int>

第二种情况是加载分区表。在这种情况下,分区是由配置单元管理的,这样可以节省昂贵的递归文件列表。在分区列上进行筛选时,spark将再次仅选择相关分区。注意 explain 计划如下:

scala> input2.where("city = 'Houston'").explain()
== Physical Plan ==

* (1) FileScan parquet default.data[id#39,state#40,city#41] Batched: true, Format: Parquet, Location: PrunedInMemoryFileIndex[file:/tmp/data/state=Texas/city=Houston], PartitionCount: 1, PartitionFilters: [isnotnull(city#41), (city#41 = Houston)], PushedFilters: [], ReadSchema: struct<id:int>

相关问题