如何使用Dynamodb进行基本聚合?

pre*_*mar 18 nosql amazon-dynamodb

如何用dynamodb实现聚合?Mongodb和couchbase都有map减少支持.

让我们说我们正在建立一个技术博客,用户可以发布文章.并且可以标记文章.

user
{
    id : 1235,
    name : "John",
    ...
}

article
{
    id : 789,
    title: "dynamodb use cases",
    author : 12345 //userid
    tags : ["dynamodb","aws","nosql","document database"]
}
Run Code Online (Sandbox Code Playgroud)

在用户界面中,我们要显示当前用户标签和相应的计数.

如何实现以下聚合?

{
    userid : 12,
    tag_stats:{
        "dynamodb" : 3,
        "nosql" : 8
    }
}
Run Code Online (Sandbox Code Playgroud)

我们将通过rest api提供这些数据,并且会经常调用它.像这样的信息显示在应用主页面中.

  • 我可以考虑在应用程序级别提取所有文档并进行聚合.但我觉得我的阅读能力单位将用尽
  • 可以使用EMR,redshift,bigquery,aws lambda等工具.但我认为这些都是出于数据仓库的目的.

我想知道其他更好的方法来实现同样的目标.考虑到成本和响应时间,人们如何实现像这样的动态简单查询选择dynamodb作为主数据存储.

Iva*_*tyk 23

长话短说:Dynamo不支持这一点.它不是为这个用例构建的.它旨在以低延迟进行快速数据访问.它根本不支持任何聚合功能.

您有三个主要选择:

  • 将DynamoDB数据导出到RedshiftEMR Hive.然后,您可以对陈旧数据执行SQL查询.这种方法的好处是它只消耗一次RCU,但你会坚持使用过时的数据.

  • DynamoDB连接器用于Hive并直接查询DynamoDB.您可以再次编写任意SQL查询,但在这种情况下,它将直接访问DynamoDB中的数据.缺点是它会在您执行的每个查询中消耗读取容量.

  • 使用DynamoDB流在单独的表中维护聚合数据.例如,您可以将表UserId作为分区键,使用带有标记和计数的嵌套映射作为属性.在原始数据的每次更新中,DynamoDB流将在主机上执行Lambda函数或某些代码以更新聚合表.这是最具成本效益的方法,但您需要为每个新查询实现其他代码.

当然,您可以在应用程序级别提取数据并在那里聚合,但我不建议这样做.除非你有一个小桌子,你需要考虑限制,只使用部分配置容量(你想消耗,比如20%的RCU用于聚合,而不是100%),以及如何在多个工人之间分配你的工作.

Redshift和Hive都已经知道如何做到这一点.Redshift在执行查询时依赖于多个工作节点,而Hive则基于Map-Reduce.此外,Redshift和Hive都可以​​使用预定义的RCU吞吐量百分比.


Tra*_*nov 8

Dynamodb 是纯键/值存储,不支持开箱即用的聚合。

如果您确实想使用 DynamoDB 进行聚合,这里有一些提示。

对于您的特殊情况,让表命名为articles. 为了进行聚合,我们需要一个额外的表user-stats来保存 userIdtag_starts

  1. 在表上启用 DynamoDB 流articles
  2. 创建一个新的 lambda 函数user-stats-aggregate,该函数订阅 DynamoDB 文章流并在articles表的每个创建/更新/删除操作中接收 OLD_NEW_IMAGES。
  3. Lambda 将执行以下逻辑
  • 如果没有旧图像,则获取当前标签,并在数据库中每次出现该用户时加 1。(请记住,可能会出现该用户没有初始记录的情况user-stats
  • 如果存在旧图像,请查看是否添加或删除了标签,并根据接收到的用户的每个受影响标签的情况应用更改 +1 或 -1。
  1. 建立一个 API 服务来检索这些用户统计信息。

通常,DynamoDB 中的聚合可以使用 DynamoDB 流、用于进行聚合的 lambda 以及以不同粒度保存聚合结果的额外表来完成。(分钟、小时、天、年...)

这带来了近乎实时的聚合,无需根据每个请求即时执行聚合数据查询。