如何设计 DynamoDB 架构来高效处理具有唯一 ID 的时间戳记录?

问题描述 投票:0回答:1

我正在设计一个 DynamoDB 架构,需要有效地满足以下用例:

用例:

  1. 获取用户按时间戳排序的前 X 条记录:

    • 我需要检索用户的最新记录,按时间戳排序。
  2. 删除某个用户的所有记录:

    • 我想删除与特定用户关联的所有记录。
  3. 删除用户单条记录:

    • 我需要根据唯一标识符删除用户的特定记录,而前端不需要知道任何 DynamoDB 特定的详细信息(例如组合键)。
  4. 如果再次提交相同数据,则更新现有记录:

    • 如果为用户再次提交相同的数据,我想用新的时间戳更新现有记录,而不是创建新记录。为了实现这一目标,我使用记录内容的 SHA-256 哈希生成
      record_id
      ,以确保相同的数据始终生成相同的
      record_id

考虑的初始设计:

设计A:

  • PK:

    USER#<user_id>

  • SK:

    RECORD#<timestamp>

  • 优点:

    • 高效检索按时间戳排序的记录。
    • 可以轻松删除某个用户的所有记录。
  • 缺点:

    • 删除单个记录很困难,因为 SK 是基于时间戳的,这使得在不知道
      PK
      SK
      的情况下识别要删除的特定记录变得很困难。
    • 更新具有相同内容的记录会创建一条新记录,而不是更新现有记录,因为时间戳发生变化,从而导致不同的 SK。

设计B:

  • PK:

    USER#<user_id>

  • SK:

    RECORD#<record_id>

  • 优点:

    • 使用独特的
      record_id
      可以轻松删除或更新单个记录。
    • 删除用户的所有记录也很简单。
  • 缺点:

    • 无法直接检索按时间戳排序的记录,因为
      record_id
      不包含时间戳。
    • SK中没有时间戳,按时间排序需要额外处理,效率不高。

考虑混合方法:

  • PK:

    USER#<user_id>

  • SK:

    RECORD#<timestamp>#<record_id>

  • 优点:

    • 允许按时间戳排序,同时保持唯一标识符。
  • 缺点:

    • 在有效删除或更新记录方面仍然面临挑战,因为必须知道确切的 SK(包括时间戳)。
    • 当仅知道
      record_id
      时,复合 SK 会使查询特定记录变得复杂。

我需要一个架构设计:

  • 允许高效检索按时间戳排序的记录。
  • 支持删除某个用户的所有记录。
  • 便于根据唯一标识符 (
    record_id
    ) 删除和更新单个记录,而不需要客户端知道确切的时间戳。
  • 确保如果再次提交相同的数据,现有记录将使用新的时间戳进行更新,而不是创建重复的记录。

如何设计一个 DynamoDB 架构来高效地满足所有这些用例?我想避免使用 GSI(因为我觉得只实现 1 个用例是一种浪费,除非确实没有办法),并且我正在寻找一种解决方案,使我能够保持前端逻辑干净,而不暴露 DynamoDB -具体细节,例如组合键(这也不是那么重要,但我认为这样更干净?)。

可以帮助我实现这一目标的最佳实践或替代方法是什么?任何指导或建议将不胜感激!

--

注意:我有一个 API,可以接收 JSON 格式的数据,我使用 sha256 对其进行哈希处理以创建该数据的唯一标识符,然后创建一个 DTO,将其发送到我的存储库,然后将数据保存到 DynamoDB,因此我的想法是,我的

ID
是在数据层之前生成的,我认为这是一个很好的做法。但即使我能够创建我的 PK&SK 作为文档的 ID,当更新并需要使用新时间戳更新文档时,它仍然会带来挑战。

是的,用户可能会多次提交相同的数据,当用户这样做时,我想做的就是保存数据,但新的时间戳会更新。

这是 NodeJs 中的一些代码,显示了我正在做的事情。

我的

controller
逻辑

    const newRecord = {
      v1: 'test',
      v2: 'test2',
      requesterUserId: '1',
    };

    await this.recordRepository.save({
      id: sha256IdFromObj(newRecord),
      timestamp: Math.floor(new Date().getTime() / 1000),
      ...newRecord,
    }, requesterUserId);

我的

repository
逻辑

    const command = new PutCommand({
      TableName: this.tableName,
      Item: {
        pk: `USER#${userId}`,
        sk: `RECORD#${queryRepoDto.id}`,
        ...queryRepoDto,
      },
    });

    await this.dynamoDBDocumentClient.send(command);

以上只是表达想法的片段。

database-design amazon-dynamodb nosql dynamodb-queries
1个回答
0
投票

以下将起作用

主表

PK
唯一ID

GSI

GSIPK GSIPK
用户ID 时间戳
© www.soinside.com 2019 - 2024. All rights reserved.