首页 > 解决方案 > DynamoDB分层数据和条件表设计

问题描述

我在设计 DynamoDB 表以支持相当简单的访问模式时遇到问题。我希望你能帮助我一点:)

我有 4 种不同的产品类型(A、B、C 和 D),它们有价格位置(国家#国家#城市)。

访问模式是:

  1. 按产品类型过滤
  2. 按产品类型位置过滤
  3. 按产品类型位置价格筛选
  4. 按产品类型位置价格过滤并按价格排序

问题是位于 USA#NY#NY 的产品必须在 USA#NY 和美国也有售。此外,用户需要能够按价格过滤并首先按贵/便宜排序。

例子:

数据:

产品:ID_1 | A型 | 地点美国#NY#NY | 价格 100 美元
产品:ID_2 | A型 | 地点 USA#NY#NY | 价格 200 美元

用例:

预期结果:

两种产品都应该以正确的顺序显示给两个用户,即使他们在不同的区域进行搜索。


为了能够按位置价格过滤并按价格排序,我想出了这个解决方案,但是,很多数据被重复了,我相信一定有更好的解决方案:

PK | SK & GSI PK | GSI SK | 其他产品详情(重复数据)
-------------------------------------------------- -------------------------
身份证 | 类型 | 价格 | 图片、名称等
身份证 | 类型#美国 | 价格 | 图片、名称等
身份证 | 类型#USA#NY | 价格 | 图片、名称等
身份证 | 类型#USA#NY#NY | 价格 | 图片、名称等

这解决了每个访问模式:

  1. 按产品类型过滤

    GSI PK = 类型

  2. 按产品类型位置过滤

    GSI PK = begin_with(TYPE#USA#NY#...)

  3. 按产品类型位置价格筛选

    GSI PK = TYPE#USA & GSI SK > 150

    GSI PK = TYPE#USA#NY & GSI SK > 150

  4. 按产品类型位置价格过滤并按价格排序

    GSI PK = TYPE#USA & GSI SK > 150 ScanIndexForward true/false

    GSI PK = TYPE#USA#NY & GSI SK > 150 ScanIndexForward 真/假

读取效率很高,但大量数据会重复(价格和产品详细信息),更新商品需要多次写入。


是否可以在不复制所有产品细节的情况下实现这一目标?

标签: amazon-web-servicesamazon-dynamodbdynamodb-queries

解决方案


我认为您误解了分层模式

您只需要
Table
PK = ID

GSI
PK = 类型
SK = 国家#州#城市

然后,您可以查询 GSI

  • 查询(GSI,PK = 'TYPEA')
  • 查询(GSI,PK = 'TYPEA',SK 以'USA#'开头)
  • 查询(GSI,PK = 'TYPEA',SK 以'USA#NY#'开头)
  • 查询(GSI,PK = 'TYPEA',SK 以'USA#NY#NY#'开头)

可以将价格过滤添加到上述任何查询中。
查询(GSI, PK = 'TYPEA', SK 以'USA#NY#NY#'开头, 过滤价格 > 100.00)

请注意,这种过滤方式不会节省任何读取容量,简单地过滤客户端可能更有效。

关键是您只需要(并且允许)表中每行 GSI 中的 1 行

唯一的问题是,您是否期望任何类型的数据超过 10GB?GSI,如 DDB 表本身每个分区有 10GB 的限制。如果您确实希望每种类型超过 10GB,我会重新考虑类型是有效访问模式的想法。没有人会滚动浏览 10GB 的数据。

老实说,我不喜欢不处理至少一种预期访问模式的 DDB 表。如果类型是驱动程序那么大,我会考虑这样的表:
Table
PK = TYPE
SK = ID

LSI
PK = (同表)
SK = COUNTRY#STATE#CITY

现在您的查询变为

  • 查询(表,PK = 'TYPEA')
  • 查询(LSI,PK = 'TYPEA',SK 以'USA#'开头)
  • 查询(LSI,PK = 'TYPEA',SK 以'USA#NY#'开头)
  • 查询(LSI,PK = 'TYPEA',SK 以'USA#NY#NY#'开头)

而且您不必为 GSI 支付额外费用。

编辑
在考虑价格过滤器时,它真的会对性能或成本产生很大影响吗?无论返回的数据是 1 行还是 100 行,您都需要为每个 1MB RCU 的数据付费。那么,您的行有多大,您希望过滤的价格差有多大?

除了发电机之外,您是否考虑过其他选择?Aurora RDS 肯定会提供您似乎需要的查询的灵活性,这要容易得多。或者也许在 DDB 之外添加 Elasticsearch。


推荐阅读