我有一个DynamoDB表,它看起来像这样:
[id] [datetime] [name] [reasonForVisit] [__typename]
[id]
是表的简单主键
[__typename]
是对于表中的所有项目具有相同值的属性
桌子变得很大了。我希望能够根据datetime
按范围过滤数据。我脑海中有两个可快速实施的选项,但不确定这是否会在成本方面产生很大影响。
- 扫描整个表格,然后按日期时间进行过滤(因为dynamodb不允许在扫描前进行过滤(
- 按固定的__typename分区创建一个GSI(partitionKey:__typename,sortKey:datetime(和QUERY,并按datetime排序键进行筛选,例如在10/18/10和10/11/10之间
所以,我的问题是,由于我的分区键对每个项目都是相同的,因此是一个大分区,我不确定当使用过滤器进行查询时,它是否仍然会读取整个表(类似于SCAN(,或者它知道如何基于过滤器有效地开始读取项目吗?
Filter总是发生在所有读取操作之后。在这种情况下,扫描和查询没有区别。此外,如果你为所有元素创建具有相同PK的GSI,你可以点击";热分区";问题,另外你会放慢你的写作速度。
如果您在表中查找80%的记录,扫描+过滤器解决方案可能非常适合。否则,您需要利用Dynamo提供的查询功能(因此通过PK和SK进行查询(。你可以做的是引入第二个记录,比如:
id(PK), datetime, name, reasonForVisit, __typename
date(PK), time(SK), id
或:
id(PK), datetime, name, reasonForVisit, __typename
date(PK), time(SK), id_list
或者如果你的数据是不可变的(历史(,并且永远不会改变,那么:
id(PK), datetime, name, reasonForVisit, __typename
date(PK), time(SK), id, name, reasonForVisit, __typename
查询给定范围将使用BatchGetItem完成。在第一个和第二个选项中,使用BatchWriteItem添加新记录时需要进行两次写入(如果严格的一致性很重要,则需要进行TransactWriteItem(。对于第三个选项,您可以在id
上使用GSI。
假设您希望按日期范围查找所有用户。
首先你想按日期排序所有用户:
type User @model @count @auth(rules: [{allow: public}]) {
id: ID!
username: String!
fullname: String
email: AWSEmail!
#...
# At the end, add this:
createdAt: String!
sortType: String @index(name: "userByDate", queryField: "userByDate", sortKeyFields: ["createdAt"]) @default(value: "User")
}
使用此解决方案,您将能够按ASC
或DESC
(使用sortDirection
(对所有条目进行排序。当然,这使得按范围datetime
检索数据更加容易,因为您不必扫描表中的所有条目。
指南
每次创建user
时,都必须将此field + value
添加到JSON
:中
sortType: User
您可以在查询中使用此筛选器后:
sortType: "User" sortDirection: ASC
源