amazon-s3 - Athena - 制作当前/最新分区

标签 amazon-s3 amazon-athena

我在 s3 中有一个数据集,并通过 Athena 进行查询。 数据集中的新分区版本每 x 分钟写入一次(Boto3/Lambda)。 最终,我需要通过 Athena SQL 高效查询“最新”版本的数据。

到目前为止,该策略正在发挥作用,但存在“问题”......

  1. 数据写入 S3,索引包含“/stamp=YYYY-MM-DD hh:mm:ss/”
  2. Athena Query 向表中添加一个新分区以获取“stamp”值,但还包括一个额外分区“Current=Yes”
  3. Athena 查询将之前“Current=Yes”的分区更改为“Current=No”

现在这一切都有效了,但我担心随着时间的推移会发生切换。 使用 Workbench/J(在 Lambda 中可能会少一些,但主体相同)

  • 添加新分区需要 1.18 - 2.56 秒。
  • 将上一个分区从“Current=Yes”更改为“Current=No”需要相同的时间(2 秒)

因此,我的数据集至少会在 2 秒内产生不正确的结果。 或者如果我先执行“current=No”,然后添加新分区,2 秒后将没有当前数据。

听起来不是很多,但是

  1. 迟早有人会调用数据来消耗同样的 2 秒。
  2. 此过程必须针对多个父/子分区运行,因此在更广泛的顶级数据集中,随时可能会发生数十个这样的切换 - 这意味着更广泛的数据集永远不会“完整”。

那么问题是 - 有没有更好的方法来实现这一目标? 能够选择“最新”版本的数据,无需复杂的 SQL 来确定子查询中每个分区的 max(stamp)。

-- first partition (earlier date)
ALTER TABLE mydb.getresources
 ADD PARTITION (ac='123456789012', `current` = 'Yes', stamp='2020-09-25T07_44_50.301984', region='us-east-1')
  LOCATION 's3://mybucket/api/resourcegroupstaggingapi/getresources/ac=123456789012/stamp=2020-09-25T07_44_50.301984/region=us-east-1/'
-- runtime 2.26s

-- second partiton (later date)
ALTER TABLE mydb.getresources
 ADD PARTITION (ac='123456789012', `current` = 'Yes', stamp='2020-09-25T08_02_50.925047', region='us-east-1')
  LOCATION 's3://mybucket/api/resourcegroupstaggingapi/getresources/ac=123456789012/stamp=2020-09-25T08_02_50.925047/region=us-east-1/'
 -- runtime 1.18s
  
-- rename old
ALTER TABLE mydb.getresources
  PARTITION (ac='123456789012', `current` = 'Yes', stamp='2020-09-25T07_44_50.301984', region='us-east-1') 
  RENAME TO PARTITION (ac='123456789012', `current` = 'No', stamp='2020-09-25T07_44_50.301984', region='us-east-1');
-- runtime 1.51s

最佳答案

遗憾的是,Glue 数据目录 API 中没有原子操作,Athena 使用该 API 来存储有关表和分区的元数据。无法以事务方式同时修改多个分区。

但是,您可以采取一些措施来缩短可能出现不一致的持续时间:直接使用 Glue 数据目录 API,而不是 Athena 的 SQL 接口(interface)。通过 Athena 比直接使用 API 慢得多。

使用CreatePartition您可以通过 API 调用添加新分区,并使用 UpdatePartition您可以修改以前的分区 - 这对应于您当前所做的操作,但会留下较短的持续时间,其中有两个分区标记为当前分区。

您可以使用 BatchUpdatePartition 做得更好:通过添加当前标志设置为 false 的新分区,然后批量更新当前分区和以前的分区以交换标志,您可以将持续时间缩短到尽可能短 – 即使不能保证查询据我了解,不会看到两个当前分区或没有当前分区,该 API 不保证是原子的。


但是,使用这样的分区键来标记最近的分区有点麻烦。使用微秒分辨率时间戳作为分区键也让我质疑你想要实现的目标是什么。 Athena 不是一个低延迟数据库,对于许多带有小文件的分区,它的性能通常非常差。用它来查找最后写入的文件永远不会很好。

我怀疑您的每个分区都包含一个文件,如果是这种情况,仅针对 S3 列表并获取对象或执行 S3 选择不是更容易且性能更高吗?

如果这不是一个选项,运行查询的进程是否可以在查询之前执行 API 调用?在这种情况下,它可以在 Glue 数据目录 API 中查找最新的分区,或列出 S3,或者您可以将最新的分区写入 Parameter Store 并从那里读取。我认为有很多方法可以改进这一点,但我没有可以帮助您的信息。

如果您更详细地描述您想要实现的目标,也许我们可以帮助您找到更有效的解决方案。

关于amazon-s3 - Athena - 制作当前/最新分区,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64060952/

相关文章:

amazon-web-services - AWS S3 存储桶权限 - 访问被拒绝

amazon-s3 - 在自定义 DelayedJob 中创建( Prawn )PDF 并将其上传到 S3?

c++ - 使用 openCV 从 Amazon S3 读取图像

ruby-on-rails - Rails 部署到 Amazon EC2 - 设备上没有剩余空间

java - 具有结构化流的 S3 检查点

python - StartQueryExecution 操作 : Unable to verify/create output bucket

amazon-web-services - 更新 AWS Athena 数据和表以重命名列

sql - AWS 雅典娜 : Convert a comma delimited string into rows

amazon-web-services - AWS Athena 看不到 Kinesis 生成的记录

sql - 递归跟踪状态数量未知的客户状态(Presto SQL)