我有一个相对简单的数据模型,我想将其存储在 DynamoDB 中。 但是,由于访问模式不同,选择主键和排序键一直很困难。 我找到了一种以适合我的模式的方式存储数据的方法,但需要具有基本相同数据的多行。 这让我觉得我错过了什么。
场景:应用程序为我们的客户管理记录,这些客户拥有大量 IOT 设备,随着时间的推移一致地报告其状态。
数据:
customer_id, device_id, timestamp, device_state, device_manufacturer
访问模式:
- 获取与
customer_id
关联的每个唯一device_id
值的最新记录。 - 获取
customer_id
的最新记录,而不考虑device_id
- 获取特定
device_id
customer_id
对timestamp
排序值。
第 2 点和第 3 点放在一起乍一看似乎很简单。 主键为customer_id
且排序键为timestamp
的表,其中主键为device_id
的 GSI,排序键为timestamp
。 通过这种设置,我不知道如何在没有非常昂贵的扫描和过滤操作的情况下实现第 1 点。 我预计桌子会变得非常大。
我的解决方案
| primary key | sort key |
| -------------------------------- | ---------------- |
| "customer_" + customer_id | timestamp |
| "device_" + device_id | timestamp |
| "latest_device_" + customer_id | device_id |
每个设备记录使用不同的关键策略更新 3 次。 使用第一个键和第二个键创建新记录,并为第三个键更新行。 上面的第 1 点使用"latest_device_"+ customer_id 键,第 2 点使用"customer_"+ customer_id,第 3 点使用"device_"+ device_id 键。
这有效,但感觉很恶心。 这让我觉得我错过了 Dynamo 的核心概念或其他一些关键点,这些关键点使我不必重复数据。
有没有办法设计我的表来避免这种数据重复,同时仍然允许我实现 3 种访问模式?
nosql 设计的第一条规则...重复是预期的。
其次,使用DDB,您不必总是自己进行复制。 DDB将通过全球二级索引(GSI)为您完成。
第三条规则,了解您的访问要求。 (干得好!
以下是我会考虑的(假设 cust/dev 没有两个时间戳是相同的)
table
hash-key : "customerId#deviceId">
sort-key : "2021-07-08T15:55:34Z">
attributes: {customer_id, device_id, timestamp, device_state, device_manufacturer}
以及带有
hash:customer_id
sort:时间戳的GSI
这将涵盖
2。获取customer_id的最新记录,而不考虑 device_id
--> 查询(gsi,hk="customerId")
3。获取特定device_id的时间戳排序值,customer_id对.
--> 查询(table,hk="customerId#deviceId")
棘手的是
- 获取与customer_id关联的每个唯一device_id值的最新记录。
我看起来有一个客户记录(可能通过DDB流+ lambda维护),其中包含该客户每个设备的最新记录数组。 假设列表足够小,可以合理地放入 DDB 记录中。基本上将其视为实际记录的一种聚合。