我正在寻找一些关于我公司已经实施的DynamoDB表的主键选择的清晰度。该表包含以下属性:
WeekStartingOn STRING (represents the Monday of the week the transaction posted)
TransactionID STRING (UUID - unique)
VendorID STRING (UUID - unique by vendor)
dccAmount NUMBER
pointOfSaleTime STRING (Storing UNIX timestamp)
TerminalID NUMBER (UUID)
表格的主键定义:
weekStartingON PRIMARY PARTITION KEY
TransactionID PRIMARY SORT KEY
当前GSI&#vendorIDIndex
VendorID PARITITON KEY
pointOfSaleTime SORT KEY
示例数据:
主要查询类型是:
For a vendor, show all the transactions in the past day, week, month, year, etc.
我认为当前布局背后的想法是将所有过去一周的交易连续分组,然后从那里选择供应商的交易。
我确定这种设计不对。使用weekStartingOn作为分区键将导致热键,因为大多数供应商都希望查看,例如,自weekStartingOn = 2016-12-05以来的所有内容。此外,按transactionID排序并没有任何意义。
我更倾向于根据vendorIDIndex定义基表主键,即
VendorID PARTITION KEY
pointOfSaleTime SORT KEY
即便如此,这个设计仍然存在一些问题。我们的一些供应商比其他供应商大得多,并且会使跨分区的读/写分配失衡。例如,VendorA可能每天有500000笔交易,但VendorB可能只有10笔日常交易。另外,我并不完全相信VendorID和pointOfSaleTime的组合是唯一的。
或者稍微复杂一点,并且需要开发人员的工作:
1 - Randomise the VendorID by adding a suffix, i.e. -1
2 - Depending on the number of suffixes, query the VendorID + Suffix, X amount of times
3 - Merge the results
我认为我喜欢最后一个选项,但考虑到目前的情况,最难实现。
最好的设计是什么?
非常感谢
答案 0 :(得分:1)
我会使用lambda函数将此表的更新流式传输到AWS ElasticSearch,以生成所需的聚合。此外,您的大多数查询似乎都是时间框,因此使用time-series tables设计模式可能是值得的。为每个月的数据准备一张表,并在旧表冷却时调整旧表的吞吐量。您被限制为256 tables per account per region,因此可能在DynamoDB中保留一年的数据并将其余数据移至较冷的存储(例如S3)。即使您将其存储在S3中,也不会失去查询+1岁数据的能力,因为现在您可以使用AWS Athena服务使用SQL查询S3存储桶。
答案 1 :(得分:0)
最后,我选择了" transactionID"的分区(主要)密钥。这是全球独一无二的,并且实现了100%的写入吞吐量。下面这个:
1)LSI是多余的。没有点具有UUID的范围键
2)我们不会在不知道VendorID的情况下直接查询transactionID。因此,要从基表获取供应商的交易,我们必须扫描所有transactionId以查找供应商的所有交易
3)需要为VendorID查询创建其他GSI。但是,我们有一个狭窄的查询条件,所以不是问题