amazon-dynamodb - 单表 DynamoDB 设计技巧
问题描述
我有一个旧应用程序,我正在对其进行现代化改造并引入 AWS。我将使用 DynamoDB 作为数据库,并希望采用单表设计。这是一个多租户应用程序。
应用程序将包括组织、网点、客户和交易。一切都源于一个组织,一个组织可以有多个网点,网点可以有多个客户,客户可以有多个交易。
访问模式预计如下:
- 通过 ID 获取客户
- 按姓名或电子邮件搜索客户
- 获取给定商店的所有客户
- 获取客户的所有交易
- 获取一个出口的所有交易
- 获取给定时间段内网点的所有交易(时间戳将与每笔交易一起存储)
- 获取给定组织的所有网点
- 通过 ID 获取 outlet
我一直在阅读单表设计并利用主键和排序键来启用这种访问,但现在我无法完全弄清楚表/模式设计。客户将附上 outletID 和 OrganiastionID,所以我应该始终知道这些 ID
数据结构(可修改)
组织:
- ID
- 姓名
- 所有者
- 奥特莱斯列表
- createdAt(时间戳)
网点:
- 组织 ID
- 分店名称
- 客户数量
- 交易数量
- createdAt(时间戳)
顾客:
- ID
- 组织 ID
- 出口编号
- 名
- 姓
- 电子邮件
- 交易总额
- 总花费
- createdAt(时间戳)
交易:
- ID
- 客户ID
- 组织 ID
- 出口编号
- createdAt(时间戳)
- 类型
- 价值
解决方案
通过彻底了解您的实体和访问模式,您有了一个良好的开端!我已经尝试为这些访问模式建模,但请记住,这不是建模解决方案的唯一方法。DynamoDB 中的数据建模是迭代的,因此这种特定设计很可能无法 100% 适合您的用例。
有了这个免责声明,让我们开始吧!
我使用data
名为 GSI1 和 GSI2 的全局二级索引 (GSI) 命名的单个表对您的访问模式进行了建模。每个 GSI 都有分别名为 GSI#PK 和 GSI#SK 的分区键和排序键。
基表模拟以下访问模式:
- 通过 ID 获取客户:
getItem where PK=CUST#<id> and SK = A
- 获取客户的所有交易:
query where PK=CUST#<id> and SK begins_with TX
- 按 ID 获取插座:
getItem where PK=ORG#<id> and SK = A
- 获取一个出口的所有客户:
query where PK=OUT#<id>#CUST
最后一种访问模式可能需要更多解释。我选择使用独特的 PK/SK 模式来模拟商店和客户之间的关系,其中 PK 是OUT#<id>#CUST
SK 是CUST#<id>
。当您的应用程序为特定客户记录交易时,它可以使用批量写入操作在 DDB中插入两条记录。批量写入操作将执行两个操作:
- 将新事务写入客户分区(例如 PK =
CUST#1
和 SK =TX#<id>
) - 将新记录写入 CUSTOMERLIST 分区(例如 PK =
OUT#<id>#CUST
和 SK =CUST#<id>
)。如果这条记录已经存在,DynamoDB 只会覆盖现有记录,这对您的用例来说很好。
转到 GSI1:
GSI1 支持以下操作:
- 按组织获取网点:
query GSI1 where GSI1PK = ORG#<id>
- 按出口获取交易:
query GSI1 where GSI1PK = OUT#<id>
- 在给定时间段内按出口获取交易:`query GSI1 where GSI1PK=OUT# and GSI1SK between and
最后,还有 GSI2
GSI2 支持以下事务:
- 按组织获取交易:
query GSI2 where GSI2PK = ORG#<id>
- 按组织获取给定时间段内的交易:
query GSI2 where GSI2PK=OUT#<id> and GSI2SK between <period1> and <period2>
对于您的最终访问模式,您已要求支持通过电子邮件或姓名搜索客户。DynamoDB非常擅长通过主键查找项目。DynamoDB不适合搜索,因为搜索需要模糊或部分匹配。如果您需要完全匹配电子邮件或姓名,您可以在 DynamoDB 中通过将 email//name 合并到 User 项目的主键中来做到这一点。
我希望这能给你一些关于如何为你的访问模式建模的想法!
推荐阅读
- javascript - 谷歌地图 - 获取英国县的坐标
- intel - SGX 本地证明样本在模拟器中返回 0x3002
- javascript - 用 2 个属性过滤 javascript 中的数组
- sql - 计算 48 小时内出现的时间记录数 - SQL
- css - 通过使用更多 CSS 来设置或删除使用 CSS 添加的元素
- java - 如何在条件中加入日期列和时间列?
- matlab - 获取参数估计的置信区间
- ms-access - 如何在 MS Access 报表宏中使用 VBA 更改记录源
- c# - 如何以 C# 形式处理 VB.net 类中的共享事件
- android - Kivy 中的 HTTPS 请求