【问题标题】:Rename S3 folder structure for Athena partitioning为 Athena 分区重命名 S3 文件夹结构
【发布时间】:2020-10-23 19:46:37
【问题描述】:

我可以访问一个 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-s3 amazon-athena


    【解决方案1】:

    您根本不需要重命名文件。虽然大多数使用Hive-style naming convention Athena 的示例确实不需要它。

    There are many ways to add partitions to an Athena table。在您的情况下,我会选择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 给出的 URI 中。分区投影非常聪明,例如,我鼓励您read the docs 了解….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 添加分区。情况并非如此,我希望我已经在上面展示过,使用该命令添加分区不是一个好主意,它适用于几个分区,但eventually it will start timing out

    【讨论】:

    • 您有没有使用timestamp 作为分区列的数据类型?它将为查询增加一些便利和验证,即使用字符串时,有人可能会意外查询where date >= '2020-01-01',这可能是一个很难发现的错误。当我将列切换到 timestamp 时,我收到以下错误,因为 Athena 似乎对格式字符串进行了 urlencode:[ErrorCategory:USER_ERROR, ErrorCode:DATA_ERROR], Detail:HIVE_INVALID_PARTITION_VALUE: Invalid partition value '2019/01/01/00' for TIMESTAMP partition key: hour=2019%2F01%2F01%2F00
    • 如果值是 ISO 格式,您可以将分区键键入为 DATE,例如2019-01-01。它与常规列没有什么不同,所发生的只是如果您说列或分区键属于某种类型,Athena 会将它们解析为该类型,如果它们不符合所需的格式,则会出现类型错误抛出。 ISO 格式是 Athena 识别的唯一日期格式。当您将分区投影添加到组合中时会变得混乱,因为您可以在那里指定日期格式,但是 PP 是一个纯粹的查询计划,它不会改变 Athena 解释数据的方式。
    • 我的问题特别是关于正斜杠。我无法更改目录结构,因为我们使用的是 AWS Firehose。 (忽略他们昨天介绍的动态分区功能)
    • 您可以更改 Kinesis Firehose 使用的前缀并获取 ISO 格式的日期,请参阅docs.aws.amazon.com/firehose/latest/dev/s3-prefixes.html
    • 感谢您的提示。它仍然没有回答我的问题。
    猜你喜欢
    • 2021-12-11
    • 2013-10-14
    • 2011-07-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多