使用 Athena 查询 S3

csz*_*zlo 3 amazon-s3 amazon-web-services amazon-athena

我设置了 Kinesis Firehose 来提取数据,AWS Lambda 执行数据转换并将传入数据放入 S3 存储桶中。S3 结构按年/月/日/小时/messages.json 组织,因此我查询的所有实际 json 文件都处于“小时”级别,所有年、月、日目录仅包含子目录。

我的问题是我需要运行查询来获取给定日期的所有数据。有没有一种简单的方法可以在“日”目录级别查询并返回其子目录中的所有文件,而无需运行 2020/06/15/00、2020/06/15/01、2020/06/15 的查询/02...2020/06/15/23?

我可以成功查询小时级目录,因为我可以创建一个表并定义 .json 文件中表示的列名称和类型,但我不确定如何在 Athena 中创建一个表(如果可能)来表示日期目录子目录而不是实际文件。

The*_*heo 8

要仅查询一天的数据而不让 Athena 读取所有天的所有数据,您需要创建一个分区表(请查看第二个示例)。分区表与常规表类似,但它们包含额外的元数据,用于描述特定分区键组合的数据所在的位置。当您运行查询并指定分区键的条件时,Athena 可以确定要读取哪些位置以及要跳过哪些位置。

\n

如何配置表的分区键取决于数据的分区方式。在您的情况下,分区是按时间划分的,并且时间戳具有每小时的粒度。您可以选择多种不同的方法来对表中的分区进行编码,哪种方法最好取决于您要运行的查询类型。您说您想按天查询,这是有道理的,并且在这种情况下效果很好。

\n

有两种设置方法:传统方法和新方法。新方法使用了几天前发布的功能,如果您尝试查找更多示例,您可能找不到很多,因此我也将向您展示传统方法。

\n

使用分区投影

\n

使用以下 SQL 创建表(您必须自己填写列,因为您说您已经成功创建了一个表,只需使用该表 \xe2\x80\x93 中的列即可修复 S3 位置):

\n
CREATE EXTERNAL TABLE cszlos_firehose_data (\n  -- fill in your columns here\n)\nPARTITIONED BY (\n  `date` string\n)\nROW FORMAT SERDE \'org.apache.hive.hcatalog.data.JsonSerDe\'\nLOCATION \'s3://cszlos-data/is/here/\'\nTBLPROPERTIES (\n  "projection.enabled" = "true",\n  "projection.date.type" = "date",\n  "projection.date.range" = "2020/06/01,NOW",\n  "projection.date.format" = "yyyy/MM/dd",\n  "projection.date.interval" = "1",\n  "projection.date.interval.unit" = "DAYS",\n  "storage.location.template" = "s3://cszlos-data/is/here/${date}"\n)\n
Run Code Online (Sandbox Code Playgroud)\n

这将创建一个按以下分区的表date(请注意,您需要在查询中引用它,例如SELECT * FROM cszlos_firehose_data WHERE "date" = \xe2\x80\xa6,因为它是保留字,如果您想避免引用它,请使用其他名称,dt似乎很受欢迎,还请注意它\'在 DDL 中用反引号转义,在 DML 语句中用双引号转义)。当您查询此表并指定 的条件date(例如 )时\xe2\x80\xa6 WHERE "date" = \'2020/06/05\',Athena 将仅读取指定日期的数据。

\n

该表使用Partition Projection,这是一项新功能,您可以将属性放在TBLPROPERTIES告诉 Athena 有关分区键以及如何查找数据 \xe2\x80\x93 的部分中,我告诉 Athena 假设存在数据从 2020 年 6 月 1 日到 S3 上的查询运行时间(必要时调整开始日期),这意味着如果您指定该时间之前或“现在”之后的日期,Athena 将知道没有此类数据,并且那些日子甚至没有尝试阅读任何东西。该storage.location.template属性告诉 Athena 在哪里可以找到特定日期的数据。如果您的查询指定了日期范围,例如\xe2\x80\xa6 WHERE "date" > \'2020/06/05\'。Athena 会生成每个日期(由属性控制projection.date.interval并由projection.date.formatformat 格式化)并读取s3://cszlos-data/is/here/2020/06/06s3://cszlos-data/is/here/2020/06/07等中的数据。

\n

您可以在文档中找到完整的Kinesis Data Firehose 示例。它展示了如何使用完整的每小时粒度的分区,但您不希望这样做,所以请坚持上面的示例。

\n

传统方式

\n

传统方式与上面类似,但是您必须手动添加分区,以便 Athena 找到它们。首先使用以下 SQL 创建表(再次添加之前实验中的列,并修复 S3 位置):

\n
CREATE EXTERNAL TABLE cszlos_firehose_data (\n  -- fill in your columns here\n)\nPARTITIONED BY (\n  `date` string\n)\nROW FORMAT SERDE \'org.apache.hive.hcatalog.data.JsonSerDe\'\nLOCATION \'s3://cszlos-data/is/here/\'\n
Run Code Online (Sandbox Code Playgroud)\n

这与上面的 SQL 完全相同,但没有表属性。如果您现在尝试对该表运行查询,您将不会得到任何结果。原因是您需要告诉 Athena 分区表的分区信息,然后它才知道在哪里查找数据(分区表必须有LOCATION,但它实际上与常规表的含义不同)。

\n

您可以通过多种不同的方式添加分区,但最直接的交互式使用是使用ALTER TABLE ADD PARTITION. 您可以在一条语句中添加多个分区,如下所示:

\n
ALTER TABLE cszlos_firehose_data ADD\nPARTITION (`date` =  \'2020-06-06\') LOCATION \'s3://cszlos-data/is/here/2020/06/06\'\nPARTITION (`date` =  \'2020-06-07\') LOCATION \'s3://cszlos-data/is/here/2020/06/07\'\nPARTITION (`date` =  \'2020-06-08\') LOCATION \'s3://cszlos-data/is/here/2020/06/08\'\nPARTITION (`date` =  \'2020-06-09\') LOCATION \'s3://cszlos-data/is/here/2020/06/09\'\n
Run Code Online (Sandbox Code Playgroud)\n

如果您开始阅读有关分区表的更多信息,您可能还会遇到该MSCK REPAIR TABLE语句作为加载分区的方式。不幸的是,这个命令真的很慢,而且它只适用于 Hive 风格的分区数据(例如\xe2\x80\xa6/year=2020/month=06/day=07/file.json)\xe2\x80\x93,所以你不能使用它。

\n