首页 > 解决方案 > 为 Athena 分区重命名 S3 文件夹结构

问题描述

我可以访问一个 S3 存储桶,其结构类似于 bucket_name/year/month/day/file.gz,每天有数百个文件。我知道要在此数据上定义分区 Athena 表,需要将其命名为 bucket_name/year=year/month=month/day=day。没有每天写一个shell脚本拼写出来(所以,一系列

aws cp --recursive s3://old_bucket/YYYY/MM/DD/* s3://new_bucket/year=YYYY/month=MM/day=DD/

对于数据集中 YYYY/MM/DD 的每个值)

有没有更简单的方法来解决这个问题?我知道,ALTER TABLE ADD PARTITION但似乎再次要求我单独指定每个分区。

标签: amazon-s3amazon-athena

解决方案


您根本不需要重命名文件。虽然大多数示例确实使用Hive 风格的命名约定,但 Athena 并不需要它。

有许多方法可以将分区添加到 Athena 表。在您的情况下,我会选择partition projection,这将使新的数据分区立即可用。或者,您可以使用手动添加分区ALTER TABLE … ADD PARTITION

要创建一个配置了分区投影的表,您可以以此为起点:

CREATE EXTERNAL TABLE my_table (
  …
)
PARTITIONED BY (
  `date` string
)
TBLPROPERTIES (
  "projection.enabled" = "true",
  "projection.date.type" = "date",
  "projection.date.range" = "2020/01/01,NOW",
  "projection.date.format" = "yyyy/MM/dd",
  "storage.location.template" = "s3://bucket_name/${date}/"
)

然后,您可以查询您的表

SELECT *
FROM my_table
WHERE "date" = '2020/10/24'

请注意,日期列/分区键是字符串而不是DATE. Athena 将获取字符串并将其插入到由storage.location.template. 分区投影非常聪明,例如,我鼓励您阅读文档以了解该….range属性的作用。

另请注意,这date是一个保留字,要在 DDL 中使用它,您必须用反引号引用它,但在查询中它需要用双引号引起来。如果您想避免总是引用,您可以将其命名为其他名称,但如果您这样做,则需要更改PARTITIONED BY部件和TBLPROPERTIES部件中的名称。

分区投影的替代方法是手动添加分区,这是一个相当新的功能。您可以使用 Glue 数据目录 API 执行此操作,在我看来,这在编写代码时更可取,或者您可以使用 DDL 执行此操作,它更紧凑且更容易适应 Stack Overflow 的答案。

假设您有一个按上述方式分区的表date(但没有,TBLPROPERTIES因为这些是特定于分区投影的),您可以添加这样的分区:

ALTER TABLE my_table ADD IF NOT EXISTS
PARTITION (`date` = '2020-10-22') LOCATION 's3://bucket_name/2020/10/22/'
PARTITION (`date` = '2020-10-23') LOCATION 's3://bucket_name/2020/10/23/'
PARTITION (`date` = '2020-10-24') LOCATION 's3://bucket_name/2020/10/24/'

然后,您可以像这样查询您的表:

SELECT *
FROM my_table
WHERE "date" = '2020-10-24'

请注意,我添加的分区的分区键值与 S3 URI 中日期的表示方式不完全对应(我以标准 ISO 方式用破折号而不是斜杠格式化日期)。手动添加分区时,分区键的值和 S3 URI 之间根本不需要任何对应关系。

有些人会告诉你,你必须对 Athena 使用 Hive 风格的分区,然后你应该使用MSCK REPAIR TABLE. 情况并非如此,正如我希望我在上面展示的那样,使用该命令添加分区不是一个好主意,它适用于几个分区,但最终它会开始超时


推荐阅读