使用 Athena 查询 S3

2023-12-23

我设置了 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 中创建一个表(如果可能)来表示日期目录子目录而不是实际文件。


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

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

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

使用分区投影

使用以下 SQL 创建表(您必须自己填写列,因为您说您已经成功创建了一个表,已经只使用该表中的列 - 还要修复 S3 位置):

CREATE EXTERNAL TABLE cszlos_firehose_data (
  -- fill in your columns here
)
PARTITIONED BY (
  `date` string
)
ROW FORMAT SERDE 'org.apache.hive.hcatalog.data.JsonSerDe'
LOCATION 's3://cszlos-data/is/here/'
TBLPROPERTIES (
  "projection.enabled" = "true",
  "projection.date.type" = "date",
  "projection.date.range" = "2020/06/01,NOW",
  "projection.date.format" = "yyyy/MM/dd",
  "projection.date.interval" = "1",
  "projection.date.interval.unit" = "DAYS",
  "storage.location.template" = "s3://cszlos-data/is/here/${date}"
)

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

该表使用分区投影 https://docs.aws.amazon.com/athena/latest/ug/partition-projection.html,这是一个新功能,您可以将属性放入TBLPROPERTIES告诉 Athena 有关分区键以及如何查找数据的部分 - 在这里,我告诉 Athena 假设 S3 上存在从 2020 年 6 月 1 日到查询运行时间的数据(调整必要的开始日期),这意味着,如果您指定该时间之前或“现在”之后的日期,Athena 将知道没有此类数据,甚至不会尝试读取这些天的任何内容。这storage.location.template属性告诉 Athena 在哪里可以找到特定日期的数据。如果您的查询指定了日期范围,例如… WHERE "date" > '2020/06/05'。 Athena 将生成每个日期(由projection.date.interval属性并格式化为projection.date.format格式)并读取数据s3://cszlos-data/is/here/2020/06/06, s3://cszlos-data/is/here/2020/06/07, etc.

你可以找到完整的文档中的 Kinesis Data Firehose 示例 https://docs.aws.amazon.com/athena/latest/ug/partition-projection-kinesis-firehose-example.html。它展示了如何使用完整的每小时粒度的分区,但您不希望这样做,所以请坚持上面的示例。

传统方式

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

CREATE EXTERNAL TABLE cszlos_firehose_data (
  -- fill in your columns here
)
PARTITIONED BY (
  `date` string
)
ROW FORMAT SERDE 'org.apache.hive.hcatalog.data.JsonSerDe'
LOCATION 's3://cszlos-data/is/here/'

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

您可以通过多种不同的方式添加分区,但最直接的交互式使用是使用ALTER TABLE ADD PARTITION https://docs.aws.amazon.com/athena/latest/ug/alter-table-add-partition.html。您可以在一条语句中添加多个分区,如下所示:

ALTER TABLE cszlos_firehose_data ADD
PARTITION (`date` =  '2020-06-06') LOCATION 's3://cszlos-data/is/here/2020/06/06'
PARTITION (`date` =  '2020-06-07') LOCATION 's3://cszlos-data/is/here/2020/06/07'
PARTITION (`date` =  '2020-06-08') LOCATION 's3://cszlos-data/is/here/2020/06/08'
PARTITION (`date` =  '2020-06-09') LOCATION 's3://cszlos-data/is/here/2020/06/09'

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

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用 Athena 查询 S3 的相关文章

随机推荐

  • IE11 中的 Angular 4 错误

    我的 Angular 4 项目可以在 Chrome 上成功运行 但是它不会在 IE11 上加载 并在 polyfills bundle js 中出现以下错误 我使用命令 ng build env prod 来构建网站 var exports
  • 如何使用 jQuery 选择空输入 (value="")

    如何检查 required 在一个部分中输入字段 然后使用 jQuery 在事件中向它们添加一个类 到目前为止 我已经尝试过 jQuery sender container input required val addClass error
  • 了解 Scrapy 中的回调

    我是 Python 和 Scrapy 的新手 我以前没有使用过回调函数 但是 我现在执行以下代码 第一个请求将被执行 其响应将被发送到定义为第二个参数的回调函数 def parse page1 self response item MyIt
  • 无限递归别名“cd”

    我想记录一下我最近的状态cd跨越我的任何一台终端 我认为一个好方法是编写一个简单的 bash 脚本包装cd bin bash cd 1 echo pwd gt tmp cwd 既然我想要cd要发生在我的终端进程中 我需要运行脚本 bette
  • 使用 SendMessage 拖放

    这听起来很有趣 只是一个小实验 我想使用发送消息模拟文件在应用程序 窗口上的拖放 是否可以 我没有该应用程序的代码 但有可执行文件的代码 该应用程序是IP 信使 http www ipmsg org index html en 我想做的是使
  • 如何快速修复导航栏的透明度?

    我有透明的导航栏 带有用于视图控制器的背景图像 但是当我向导航栏添加栏按钮项目时 它变得像第二张图片中那样 如何让栏按钮项目也完全透明的导航栏 我使用下面的这些代码使导航栏透明 extension UINavigationControlle
  • IntelliJ 的选择字体对话框中没有出现字体

    我用这个安装了 Monaco 字体code https gist github com rogerleite 99819 然而 它并没有出现在Setting gt Editor gt Color and fonts gt Font 我应该怎
  • 如何在Windows Azure中使用子域?

    我目前已将 domain com 分配给我的 azure 网站 但我想知道使用子域需要什么 我想我需要在 godaddy 创建一个 CNAME 但我要指出什么呢 每个子域如何指向我的解决方案中的每个文件夹 为此我需要网络角色吗 我不知道如何
  • 64位类型和操作是如何在32位架构的最低层实现的?

    像 int64 t 这样的类型如何在最低 即汇编级别 上实现 我使用的是 32 位机器 但仍然可以使用 int64 t 例如 我最初的假设是 64 位只是模拟的 因此在 32 位机器上与 32 位数据类型相比 这些类型的计算必须有相当多的开
  • 在 Swift 中将 NSUnderlineStyle.PatternDash 添加到 NSAttributedString 中?

    我正在尝试为 Swift 应用程序中的某些文本添加下划线 这是我目前拥有的代码 let text NSMutableAttributedString string self currentHome name let attrs NSUnde
  • TSQL问题计算一个表中两个日期之间的差异

    在 MSSQL 2008 中 我的表和数据如下所示 create table tempData user id int type varchar 10 ts datetime insert into tempData select 1 EN
  • 如何正确使用goto语句

    我正在上高中 AP 计算机科学课程 我决定扔一个goto声明进入我们的一个实验室只是为了玩玩 但我得到了这个错误 Exception in thread main java lang Error Unresolved compilation
  • 在发布时替换 ASP.NET Core 与 2017 中的 web.config

    我正在尝试将 web config 替换为生产版本 我有生产版本 production web config tilda 作为我的项目文件夹的根 我在迁移文档中找到了这个
  • (Postgresql 中的一对多关系

    我有两张桌子 posts id other stuff tags 1
  • 在 PHP 5.4.0 之前版本的匿名函数中使用 `$this`

    PHP 手册指出 无法使用 this来自 PHP 之前的匿名函数 5 4 0 on the 匿名函数页面 http php net manual en functions anonymous php 但我发现我可以通过分配使其工作 this
  • 从字符串中删除特定单词

    我正在通过 JSON 提取 Twitter 用户的个人资料图像 为此我的代码是 x gt profile image url 返回个人资料图像的 url url 的格式可能是 xyz normal jpg or xyz normal png
  • 当子窗体在 Delphi 中可见时,如何防止父窗体中的操作执行

    我有一个主窗体和一个非模态的浮动子窗体 主窗体有一个名为DeleteAction 的TAction 其快捷方式为Delete 当浮动窗体可见并且按下删除键时 将执行主窗体的DeleteAction 如何防止快捷方式通过子窗体传递到父窗体 我
  • 为什么 iconv 命令输出到同一文件会被截断?

    现在我有一些 euc jp 编码的文件需要转换为 utf 8 编码 所以我在 bash 中使用 iconv 命令 iconv foo c f euc jp t utf 8 o foo c 但是出现了一个问题 它说 usr bin iconv
  • 如何迭代 ElementTree 中的子文本节点(不是后代)?

    给定一个这样的元素 a hello a
  • 使用 Athena 查询 S3

    我设置了 Kinesis Firehose 来提取数据 AWS Lambda 执行数据转换并将传入数据放入 S3 存储桶中 S3 结构按年 月 日 小时 messages json 组织 因此我查询的所有实际 json 文件都处于 小时 级