我有一个关于dynamodb的问题,或者更确切地说,如何建模一个表。
问题描述:
目标:用户可以保存产品的价格警报。
例如:当产品x的价格低于目标价格时,用户希望保存警报。
我要特别坚持的是:产品、用户id、targetprice、operator。
运算符可以等于、小于或大于(在持久化之前,我将在步骤中验证这些值)。
用户可以为目标价格和/或运营商不同的同一产品添加多个警报。如果所有这些属性都相同,则不应在数据库中创建重复项。
当然,每个用户的警报应该完全分开。
我的主要“阅读”案例是获取产品的所有警报。
我当前的解决方案是将产品作为主键(每当我提到产品时,而不是讨论产品的唯一标识符),并将alertid作为排序键。
alertid是所有属性的组合键:product:userId:targetPrice:operator
。
例如:greatBook12:1234:34:lesser
。
下面是节点中用于持久化警报的一些示例代码:
const params = {
TableName: TABLE_NAME,
Item: {
userId,
alertId: `${product}:${userId}:${targetPrice}:${operator}`,
product,
targetPrice,
operator
},
ReturnValues: 'ALL_OLD'
};
docClient.put(params) // ...
我的问题是:
像那样滥用排序键感觉有点不对。虽然它涵盖了我的所有需求(没有重复,阅读很容易,应该比较快),但我想知道是否没有更好的方法来做到这一点。也许是指数之类的?
我有点喜欢扁平的数据结构(只是表中的项目),但也许有另一种方法可以为不同的targetprices/operators/products/users创建唯一的警报,而不创建重复项?
所以我想我的问题是:有没有更好的方法来满足我的工作要求?
非常感谢你提前!
最佳答案
很有趣的问题。一方面,使用product
分区键可以查询简单性,但也可以不均匀地分布数据。如果一个产品获得了巨大的成功,并承担了50%的负载(“热分区”问题在这里详述https://cloudonaut.io/dynamodb-pitfall-limited-throughput-due-to-hot-partitions/)?在这种情况下,你可能会遇到读或写抛出。dynamodb建议使用一些随机性(例如随机值(11000))来避免这种不均匀分布。您可以在这里了解有关这些策略的更多信息:https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/bp-partition-key-sharding.html#bp-partition-key-sharding-random
但这取决于您如何确定热分区风险。如果您确定没有它们(警报比其他产品多得多的产品),那么现在最好保持模式简单一些?