繁体   English   中英

DynamoDB 表设计:我如何 model 建立一对多关系,我需要所有“一”项和按某些属性排序的“多”项之一

[英]DynamoDB Table Design: How do I model a one to many relationship where I need all of the "one" items and one of "many" sorted by some attribute

我的整个职业生涯都在使用非规范化的关系数据库。 为了实现一个单表设计,可以在类似“App Store”的个人项目上处理几个特定的访问模式,我很难忘记所有这些。

这是一个快速的 ERD。 有一个应用程序 model 由平台(iOS、Android)和捆绑标识符以及创建新版本时使用的默认值 map 标识。 每个 App 可以有 0 到多个版本,这些版本由版本号标识(这是一个连续的数值,并且在 App 的上下文中是唯一的)。 一个版本具有 IsReleased 属性以及其他几个属性(如名称、发行说明、二进制路径等)。

访问模式

  1. 列出每个应用程序的最新版本。
  2. 列出给定平台的每个应用程序的最新版本。
  3. 列出 IsReleased 为 1 的每个应用程序的最新版本。
  4. 列出 IsReleased 为 1 的给定平台的每个应用程序的最新版本。
  5. 获取特定应用的最新版本。
  6. 获取 IsReleased 为 1 的特定应用的最新版本。
  7. 获取特定应用的所有版本。
  8. 获取 IsReleased 为 1 的特定应用的所有版本。
  9. 获取特定应用的默认属性。

我遇到了 1 到 4 的问题,这张桌子是我要去的地方。 我很难使用 GSI,它会按排序顺序为我提供单个版本的所有应用程序项目。

PK sk 默认值 应用名称 版本 被释放 其他属性
app_ios_com.app.one defaults {... json... }
app_ios_com.app.one version_1 应用一 1 1
app_ios_com.app.one version_2 应用一 2 1
app_ios_com.app.one version_3 应用一 3 1
app_ios_com.app.two defaults {... json... }
app_ios_com.app.two version_1 应用二 1 1
app_ios_com.app.two version_2 应用二 2 0
app_ios_com.app.two version_3 应用二 3 0

例如,对于访问模式 1,我想要:

PK sk 默认值 应用名称 版本 被释放 其他属性
app_ios_com.app.one version_3 应用一 3 1
app_ios_com.app.two version_3 应用二 3 0

例如,对于访问模式 3,我想要:

PK sk 默认值 应用名称 版本 被释放 其他属性
app_ios_com.app.one version_2 应用一 3 1
app_ios_com.app.two version_1 应用二 1 1

我必须记住的一些数据限制:

  • 目前只有10到20个应用程序,但我需要能够支持数百个
  • 大多数应用程序将有 100 到 200 个版本,其中有 20 到 30 个发布版本。 最大的应用程序有 1000 个版本,其中发布了 50 个。
  • 在后端,IsReleased 标志通常会从 0 切换到 1,但偶尔会从 0 切换到 1。
  • 平均版本项约为 2 KB。
  • IsReleased 为 1 的访问模式变化更频繁地使用。

我觉得解决方案就在我面前,但我不能指望它。

TLDR; 想到的解决方案是排行榜模式,用于在单独的记录中缓存最新的应用程序版本。 每当添加新版本时, DynamoDB Streams都会将更改作为事件发送到 lambda,然后再更新非规范化的最新记录。

注意:您出色的文章中缺少一条信息:您需要多久执行一次latest查询? 如果不是很频繁,那么“扫描并完成”将适用于您当前的卷。 如果答案是每分钟 1k 个latest查询,那么情况就不同了。 好消息是您的基本表格设计是可靠的。 当出现性能/成本问题时,可以增量实施Latest的查询优化,而不会弄乱表设计。

非规范化最新版本

我们将保留最新版本的非规范化副本,这是另一种听起来很罪恶的DynamoDB 模式 当添加版本或更改发布状态时,流触发的 lambda 将使用更新 API 更新这些记录。 如何存储最新版本信息? 我们有几种选择:

  1. 将所有latest数据存储在具有 map 属性{app1: {latest version copy}, app2: ...}的 singleton 记录中。 您可以将更多逻辑放入记录中以处理isReleased项目,或者简单地获取记录并在后端进行过滤。
  2. 使用每个应用程序一条记录的全球二级索引。 每条记录都有“最新”作为 app_id 的 GSI1PK 和app_id 记录具有与#1 中相同的信息。
  3. 用作 GSI,每个应用程序有多个记录。 像这样的东西似乎有效。 例如,查询 #4 将使用GSI1PK=Latest#Released AND begins_with(GSI1SI, "IOS")
GSI1PK              GSI1SK
Latest              app_ios_com.app.one
Latest              IOS#app_ios_com.app.one
Latest#Released     app_ios_com.app.one
Latest#Released     IOS#app_ios_com.app.one

注意:如果您有高查询量和低基数, 热分区可能是这些“排行榜”类型非正规化模式的问题。 如果这成为一个问题,您可以通过保留每个“最新”记录的多个副本来解决它,例如,随机查询 X 个副本latest-copy1latest-copy2latest-copy3 Amazon 使用计算后缀调用此模式分片

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM