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

时间:2017-05-24 06:03:17

标签: amazon-dynamodb nosql

如何通过dynamodb实现聚合? Mongodb和couchbase都有地图缩减支持。

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

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

article
{
    id : 789,
    title: "dynamodb use cases",
    author : 12345 //userid
    tags : ["dynamodb","aws","nosql","document database"]
}

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

如何实现以下聚合?

{
    userid : 12,
    tag_stats:{
        "dynamodb" : 3,
        "nosql" : 8
    }
}

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

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

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

3 个答案:

答案 0 :(得分:14)

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

您有三个主要选择:

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

  • 对Hive使用DynamoDB connector并直接查询DynamoDB。您可以再次编写任意SQL查询,但在这种情况下,它将直接访问DynamoDB中的数据。缺点是它会消耗你每次查询的读取容量。

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

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

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

答案 1 :(得分:0)

DynamoDB不支持此功能。您可以在DynamoDB上创建二级索引,但这将需要其他DynamoDB容量单位。 DynamoDB是快速的键值存储,这意味着它不具有执行复杂的聚合,排序,相关性等功能。

您需要将数据导出到数据存储。您可以通过dynamoDB-Glue-S3导出器https://aws.amazon.com/about-aws/whats-new/2018/07/aws-glue-now-supports-reading-from-amazon-dynamodb-tables/将其导出到S3。然后使用AWS Athena发出标准SQL查询来进行聚合。尝试此操作时,我发现SQL查询有时返回数据的速度很慢,尤其是在聚合复杂或数据大小很大时。

另一种方法是将Rockset与DynamoDB表连接。我发现这个描述Decore加密货币分析的用例非常类似于您的需求https://rockset.com/blog/case-study-decore-uses-rockset-for-search-and-analytics-on-dynamodb/。此案例研究显示了Rockset上的SQL查询如何快速完成并在几百毫秒内完成。

答案 2 :(得分:0)

Dynamodb是纯键/值存储,不支持现成的聚合。

如果您真的想使用DynamoDB进行聚合,请参考以下提示。

对于您的特殊情况,让我们命名名为articles的表。 要进行汇总,我们需要一个额外的表user-stats,其中包含userIdtag_starts

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

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

这带来了近乎实时的聚合,而无需在每次查询聚合数据时都立即进行。