如何告诉 Spark 根据范围跳过分区

Posted

技术标签:

【中文标题】如何告诉 Spark 根据范围跳过分区【英文标题】:How to tell Spark to skip partitions based on a range 【发布时间】:2021-05-16 15:49:44 【问题描述】:

假设我有 100 个文件存储在 S3 中,属于我想使用 Spark SQL 查询的一个表。假设该表有一个 timestamp 列和其他一些列。时间戳是单调递增的,因此每个分区中的时间戳都是有序的,并且小于所有后续分区中的所有时间戳。

我现在想对这些文件进行查询,其中我有一个谓词timestamp between t1 and t2timestamp > t1,其中t1 可能是这100 个分区中间的时间戳。据我了解,Spark 目前无法确定时间戳在我的分区中是有序的,因此必须检查所有 100 个分区中的每一行并查看其时间戳。

我的问题是:如何让 Spark 变得更智能并跳过整个分区?例如,如果t1 在这 100 个分区的中间,我该如何教 Spark 跳过前 50 个分区?

我知道分区发现https://spark.apache.org/docs/latest/sql-data-sources-parquet.html#partition-discovery,但据我所知,这仅适用于“分类”分区,如gender=male,不适用于范围。我最好的选择是什么?

【问题讨论】:

你的数据格式是什么?是 Delta Lake、parquet 文件、csv 吗? 我们数据的格式是parquet 【参考方案1】:

我的情况基本相同,数据位于 /root/tenant=tenantId/date=2021-01-01 之类的文件夹中,我使用 spark 表达式(在 python 上)

from pyspark.sql.functions import to_date as fdate

events_df = spark.read.parquet('/root') \
        .filter(events_df.tenant_id == tenant_id) \
        .filter((from_date <= fdate(events_df.date, 'yyyy-MM-dd'))
                & (fdate(events_df.date, 'yyyy-MM-dd') <= to_date)) \
        .filter(col('item_name').isin(['val1', 'val2', 'val3'])) \
        .select(col('date').alias('file_date'),
                'device_id',
                'dataset_context_id',
                col('free').cast('float').alias('free'),
                'item_time')

我有以下执行计划:

== Physical Plan ==
*(1) Project [date#13 AS file_date#54, device_id#0, dataset_context_id#1, cast(free#9 as float) AS free#55, item_time#6]
+- *(1) Filter item_name#7 IN (val1,val2,val3)
   +- FileScan parquet [device_id#0,dataset_context_id#1,item_time#6,item_name#7,item_data#9,tenant_id#12,date#13] Batched: false, DataFilters: [item_name#7 IN (val1,val2,val3)], Format: Parquet, Location: InMemoryFileIndex(1 paths)[<path/to/root/>], PartitionFilters: [isnotnull(tenant_id#12), (tenant_id#12 = <tenantId>), (cast(cast(gettimestamp(date#13, yyyy-..., PushedFilters: [In(item_name, [val1,val2,val3])], ReadSchema: struct<device_id:string,dataset_context_id:string,item_time:timestamp,item_name:string,item_data:...

如你所见,计划中有PartitionFilters,这证明spark在日期范围内运行分区过滤。 (火花 3.1.1)

【讨论】:

以上是关于如何告诉 Spark 根据范围跳过分区的主要内容,如果未能解决你的问题,请参考以下文章

GlobalMapper精品教程008:如何根据指定区域(shpkmlcad)下载卫星影像?

GlobalMapper精品教程008:如何根据指定区域(shpkmlcad)下载卫星影像?

以宝塔Linux为例讲解CentOS如何挂载磁盘

spark页面单跳转化率

如何告诉 Cppcheck 跳过头文件

如何在mapgis中将点的属性赋给区