DynamoDB的扫描与查询(对于GSI,哪个分区键对于整个表是相同的)过滤成本



我有一个DynamoDB表,它看起来像这样:

[id] [datetime] [name] [reasonForVisit] [__typename]

[id]是表的简单主键

[__typename]是对于表中的所有项目具有相同值的属性

桌子变得很大了。我希望能够根据datetime范围过滤数据。我脑海中有两个可快速实施的选项,但不确定这是否会在成本方面产生很大影响。

  1. 扫描整个表格,然后按日期时间进行过滤(因为dynamodb不允许在扫描前进行过滤(
  2. 按固定的__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")
}

使用此解决方案,您将能够按ASCDESC(使用sortDirection(对所有条目进行排序。当然,这使得按范围datetime检索数据更加容易,因为您不必扫描表中的所有条目。

指南

每次创建user时,都必须将此field + value添加到JSON:中

sortType: User

您可以在查询中使用此筛选器后:

sortType: "User" sortDirection: ASC

最新更新