4

我在 AWS Dynamodb 中有一个包含 100 万条记录的表。是否可以在一个查询中使用 dynamodb 中的附加排序键条件查询主键值数组?我正在使用我的服务器端逻辑。

这是参数

var params = {
TableName: "client_logs",
KeyConditionExpression: "#accToken = :value AND ts between :val1 and 
:val2", 
ExpressionAttributeNames: {
"#accToken": "acc_token"
},
ExpressionAttributeValues: {
        ":value": clientAccessToken,
        ":val1": parseInt(fromDate),
        ":val2": parseInt(toDate),
        ":status":confirmStatus
},
FilterExpression:"apiAction = :status"


};

这里 acc_token 是主键,我想在一个查询中查询 access_token 值数组。

4

2 回答 2

1

不,这是不可能的。单个查询可能只搜索一个特定的哈希键值。(请参阅DynamoDB – 查询。)

但是,您可以并行执行多个查询,这将产生您想要的效果。

编辑 (2018-11-21)

由于您说您正在寻找 200 多个哈希键,因此这里有两种可能的解决方案。这些解决方案不需要对 DynamoDB 进行无限制的并行调用,但它们会花费您更多的 RCU。它们可能更快或更慢,具体取决于表中数据的分布。

我不知道你的数据分布,所以我不能说哪一个最适合你。在所有情况下,我们都不能acc_token用作 GSI 的排序键,因为您不能IN在 KeyConditionExpression 中使用运算符。(请参阅DynamoDB – 条件。)

解决方案 1

该策略基于Global Secondary Index Write Sharding for Selective Table Queries

脚步:

  1. 向您写入表的项目添加新属性。这个新属性可以是数字或字符串。让我们称之为index_partition
  2. 当您向表中写入新项目时,请为其指定一个从0Nfor的随机值index_partition。(在这里,N是您选择的任意常数。9可能是一个不错的值开始。)
  3. 创建一个 GSI,其哈希键为index_partition,排序键为ts。您将需要投影apiActionacc_tokenGSI。
  4. 现在,您只需要执行N查询。使用关键条件表达式index_partition = :n AND ts between :val1 and :val2和过滤器表达式apiAction = :status AND acc_token in :acc_token_list

解决方案 2

此解决方案与上一个类似,但我们将使用基于日期的 GSI 分区,而不是使用随机 GSI 分片。

脚步:

  1. 向您写入表的项目添加新的字符串属性。让我们称之为ts_ymd
  2. 当您向表中写入新项目时,只需使用 的yyyy-mm-dd一部分ts来设置 的值ts_ymd。(您可以使用任何您喜欢的粒度。这取决于您对 . 的典型查询范围ts。如果:val1并且:val2通常彼此之间仅相隔一个小时,那么合适的 GSI 分区键可能是 yyyy-mm-dd-hh。)
  3. 创建一个 GSI,其哈希键为ts_ymd,排序键为ts。您将需要投影apiActionacc_tokenGSI。
  4. 假设您使用 yyyy-mm-dd 作为 GSI 分区键,您只需为:val1and内的每一天执行一个查询:val2。使用关键条件表达式ts_ymd = :ymd AND ts between :val1 and :val2和过滤器表达式apiAction = :status AND acc_token in :acc_token_list

解决方案 3

我不知道apiAction有多少不同的值以及这些值是如何分布的,但如果有多个,并且它们的分布大致相等,您可以根据该值对 GSI 进行分区。您对 的可能值越多apiAction,此解决方案就越适合您。这里的限制因素是您需要有足够的值,以免您的 GSI 遇到 10GB 分区限制。

脚步:

  1. 创建一个 GSI,其哈希键为apiAction,排序键为ts。您将需要投影acc_token到 GSI。
  2. 您只需要执行一个查询。apiAction = :status AND ts between :val1 and :val2" and a filter expression of在 :acc_token_list 中使用 acc_token 的键条件表达式。

对于所有这些解决方案,您应该考虑 GSI 分区键的分布有多均匀,以及ts查询中典型范围的大小。您必须在 上使用过滤器表达式acc_token,因此您应该尝试选择一个最小化与您的关键条件表达式匹配的项目总数的解决方案,但同时,您需要注意您不能超过10GB 数据用于一个分区键(用于表或 GSI)。您还需要记住,GSI 只能作为最终一致性读取进行查询。

于 2018-11-21T19:51:41.113 回答
0

您可以在PartiQL SELECT 查询的帮助下有效地查询分区键范围并在排序键上应用附加条件。官方 DDB 文档说:

为确保 SELECT 语句不会导致全表扫描,WHERE 子句条件必须指定分区键。使用相等或 IN 运算符。

该文档没有特别提到排序键,但它说对非键属性的额外过滤仍然不会导致完全扫描。因此,我几乎可以肯定,使用支持的运算符之一的排序键条件不会导致表扫描,执行速度快并且消耗尽可能少的容量单位。

因此,您的查询可能如下所示:

SELECT * FROM client_logs WHERE acc_token IN (t1, t2, ...) AND ts BETWEEN t1 AND t2

可以在此处找到 PartiQL API 使用的 Node.js 示例。

于 2021-07-18T18:09:19.897 回答