Amazon Kinesis Data Firehose 示例 - Amazon Athena

本文属于机器翻译版本。若本译文内容与英语原文存在差异,则一律以英文原文为准。

Amazon Kinesis Data Firehose 示例

当您使用 Kinesis Data Firehose 将数据传输到 Amazon S3 时,默认配置会使用类似于以下示例的键写入对象:

s3://bucket/prefix/yyyy/MM/dd/HH/file.extension

要创建在查询时自动查找分区的 Athena 表,而不必在新数据到达时将它们添加到 AWS Glue Data Catalog,您可以使用分区投影。

以下 CREATE TABLE 示例使用默认 Kinesis Data Firehose 配置。

CREATE EXTERNAL TABLE my_ingested_data ( PARTITIONED BY ( datehour STRING LOCATION "s3://DOC-EXAMPLE-BUCKET/prefix/" TBLPROPERTIES ( "projection.enabled" = "true", "projection.datehour.type" = "date", "projection.datehour.format" = "yyyy/MM/dd/HH", "projection.datehour.range" = "2021/01/01/00,NOW", "projection.datehour.interval" = "1", "projection.datehour.interval.unit" = "HOURS", "storage.location.template" = "s3://DOC-EXAMPLE-BUCKET/prefix/${datehour}/" )

CREATE TABLE 语句中的 TBLPROPERTIES 子句告诉 Athena 以下内容:

当您查询表时,Athena 会计算 datehour 值并使用存储位置模板生成分区位置列表。

使用 date 类型

当您使用投影分区键的 date 类型时,您必须指定一个范围。由于在创建 Kinesis Data Firehose 传输流之前没有日期数据,您可以使用创建日期作为开始日期。此外,由于您没有将来日期的数据,您可以使用特殊令牌 NOW 作为结束日期。

CREATE TABLE 示例中,开始日期指定为 UTC 时间 2021 年 1 月 1 日午夜。

注意

配置一个与您的数据尽可能匹配的范围,以便 Athena 仅查找现有分区。

在示例表上运行查询时,Athena 将 datehour 分区键上的条件与范围结合使用来生成值。请考虑以下查询:

SELECT * FROM my_ingested_data WHERE datehour >= '2020/12/15/00' AND datehour < '2021/02/03/15'

SELECT 查询中的第一个条件使用在 CREATE TABLE 语句指定的日期范围开始之前的日期。由于分区投影配置没有为 2021 年 1 月 1 日之前的日期指定分区,因此 Athena 仅在以下位置查找数据,并忽略查询中较早的日期。

s3://bucket/prefix/2021/01/01/00/ s3://bucket/prefix/2021/01/01/01/ s3://bucket/prefix/2021/01/01/02/ s3://bucket/prefix/2021/02/03/12/ s3://bucket/prefix/2021/02/03/13/ s3://bucket/prefix/2021/02/03/14/

同样,如果查询在 2021 年 2 月 3 日 15:00 之前的日期和时间运行,则最后一个分区将反映当前日期和时间,而不是查询条件中的日期和时间。

如果您想查询最新数据,您可以利用 Athena 不生成未来日期的事实,并仅指定起始 datehour ,如以下示例所示。

SELECT * FROM my_ingested_data WHERE datehour >= '2021/11/09/00'

选择分区键

您可以指定分区投影如何将分区位置映射到分区键。在 CREATE TABLE 示例中,日期和小时被合并成一个名为 datehour 的分区键,但也可以使用其他方案。例如,您还可以为年、月、日和小时配置具有单独分区键的表。

当日和小时有各自单独的条件时,查询会更容易读取。考虑到这一点,以下 CREATE TABLE 示例将日期与小时分开。

CREATE EXTERNAL TABLE my_ingested_data2 ( PARTITIONED BY ( day STRING, hour INT LOCATION "s3:// DOC-EXAMPLE-BUCKET / prefix /" TBLPROPERTIES ( "projection.enabled" = "true", "projection.day.type" = "date", "projection.day.format" = "yyyy/MM/dd", "projection.day.range" = "2021/01/01,NOW", "projection.day.interval" = "1", "projection.day.interval.unit" = "DAYS", "projection.hour.type" = "integer", "projection.hour.range" = "0,23", "projection.hour.digits" = "2", "storage.location.template" = "s3:// DOC-EXAMPLE-BUCKET / prefix /$ { day}/$ { hour}/"

在示例 CREATE TABLE 语句中,小时是一个单独的分区键,配置为整数。小时分区键的配置指定了 0 到 23 的范围,并且当 Athena 生成分区位置时,小时的格式应为两位数。

my_ingested_data2 表的查询可能如下所示:

SELECT * FROM my_ingested_data2 WHERE day = '2021/11/09' AND hour > 3

分区键类型和分区投影类型

请注意,第一个 CREATE TABLE 示例中的 datehour 键在分区投影配置中配置为 date ,但分区键的类型为 string 。第二个示例中的 day 也是如此。分区投影配置中的类型仅告诉 Athena 在生成分区位置时如何格式化值。您指定的类型不会更改分区键的类型 – 在查询中, datehour day 属于 string 类型。

当查询包含与 day = '2021/11/09' 类似的条件时,Athena 会使用分区投影配置中指定的日期格式解析表达式右侧的字符串。在 Athena 验证日期是否在配置范围内后,它会再次使用日期格式将日期作为字符串插入到存储位置模板中。

同样,对于像 day > '2021/11/09' 这样的查询条件,Athena 会解析右侧并生成配置范围内所有匹配日期的列表。然后使用日期格式将每个日期插入到存储位置模板中以创建分区位置列表。

编写与 day > '2021-11-09' day > DATE '2021-11-09' 相同的条件将无效。在第一种情况下,日期格式不匹配(注意连字符而不是正斜杠),在第二种情况下,数据类型不匹配。

使用自定义前缀和动态分区

Kinesis Data Firehose 可以使用 自定义前缀 动态分区 进行配置。使用这些功能,您可以配置 Amazon S3 键并设置更好地支持您的使用案例的分区方案。您还可以将分区投影与这些分区方案一起使用,然后进行相应的配置。

例如,您可以使用自定义前缀功能获取具有 ISO 格式日期而非默认 yyyy/MM/dd/HH 方案的 Amazon S3 键。

您还可以将自定义前缀与动态分区结合使用,以从 Kinesis Data Firehose 消息中提取 customer_id 之类的属性,如以下示例所示。

prefix/!{timestamp:yyyy}-!{timestamp:MM}-!{timestamp:dd}/!{partitionKeyFromQuery:customer_id}/

使用该 Amazon S3 前缀,Kinesis Data Firehose 传输流会将对象写入 s3://bucket/prefix/2021-11-01/customer-1234/file.extension 等键。对于像 customer_id 这样的属性,其值可能事先未知,您可以使用分区投影类型 injected 并使用如下所示的 CREATE TABLE 语句:

CREATE EXTERNAL TABLE my_ingested_data3 ( PARTITIONED BY ( day STRING, customer_id STRING LOCATION "s3://DOC-EXAMPLE-BUCKET/prefix/" TBLPROPERTIES ( "projection.enabled" = "true", "projection.day.type" = "date", "projection.day.format" = "yyyy-MM-dd", "projection.day.range" = "2021-01-01,NOW", "projection.day.interval" = "1", "projection.day.interval.unit" = "DAYS", "projection.customer_id.type" = "injected", "storage.location.template" = "s3://DOC-EXAMPLE-BUCKET/prefix/${day}/${customer_id}/"

当您查询具有类型 injected 的分区键的表时,您的查询必须包含该分区键的值。对 my_ingested_data3 表的查询可能如下所示:

SELECT * FROM my_ingested_data3 WHERE day BETWEEN '2021-11-01' AND '2021-11-30' AND customer_id = 'customer-1234'

ISO 格式日期

由于 day 分区键的值是 ISO 格式的,您也可以使用 DATE 类型而不是 STRING 类型作为日期分区键,如以下示例所示:

PARTITIONED BY (day DATE, customer_id STRING)

查询时,此策略允许您在分区键上使用日期函数而无需解析或转换,如以下示例所示: