38

dynamodb 如何实现聚合?Mongodb 和 couchbase 有 map reduce 支持。

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

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 作为主要数据存储来实现像这样的动态简单查询。

4

2 回答 2

49

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

您有三个主要选择:

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

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

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

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

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

于 2017-07-29T14:36:32.183 回答
4

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

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

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

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

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

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

于 2020-08-19T11:55:13.630 回答