我在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值的数组。
答案 0 :(得分:0)
否,这是不可能的。单个查询只能搜索一个特定的哈希键值。 (请参见DynamoDB – Query。)
但是,您可以并行执行多个查询,这将达到您想要的效果。
编辑(2018-11-21)
由于您说的是要查找的200多个哈希键,因此这里有两种可能的解决方案。这些解决方案不需要对DynamoDB进行无限制的并行调用,但是它们将使您花费更多的RCU。它们可能更快或更慢,具体取决于表中数据的分布。
我不知道您的数据分布,所以我不能说哪个数据最适合您。在所有情况下,我们都不能使用acc_token
作为GSI的排序键,因为您不能在KeyConditionExpression中使用IN
运算符。 (请参见DynamoDB – Condition。)
解决方案1
此策略基于Global Secondary Index Write Sharding for Selective Table Queries
步骤:
index_partition
。0
赋予一个从N
到index_partition
的随机值。 (在这里,N
是您选择的任意常数。9
可能是一个不错的值。)index_partition
和排序键ts
创建一个GSI。您需要将apiAction
和acc_token
投影到GSI。N
个查询。使用关键条件表达式index_partition = :n AND ts between :val1 and :val2
和过滤条件表达式apiAction = :status AND acc_token in :acc_token_list
解决方案2
此解决方案与上一个类似,但是我们将使用基于日期的分区作为GSI,而不是使用随机GSI分片。
步骤:
ts_ymd
。yyyy-mm-dd
的{{1}}部分来设置ts
的值。 (您可以使用任何喜欢的粒度。这取决于您对ts_ymd
的典型查询范围。如果ts
和:val1
通常彼此仅相隔一个小时,则可以使用合适的GSI分区密钥可以是yyyy-mm-dd-hh。):val2
和排序键ts_ymd
创建一个GSI。您需要将ts
和apiAction
投影到GSI。acc_token
和:val1
内每天执行一次查询。使用关键条件表达式:val2
和过滤条件表达式ts_ymd = :ymd AND ts between :val1 and :val2
解决方案3
我不知道apiAction = :status AND acc_token in :acc_token_list
有多少个不同的值以及这些值是如何分布的,但是如果有多个以上的值,并且它们具有大致相等的分布,则可以根据以下内容对GSI进行分区那个价值。 apiAction
的值越多,此解决方案越适合您。这里的限制因素是,您需要具有足够的值,以免GSI的10GB分区限制不足。
步骤:
apiAction
和排序键apiAction
创建一个GSI。您需要将ts
投影到GSI。acc_token
acc_token的关键条件表达式。对于所有这些解决方案,您应考虑GSI分区键的分布均匀程度,以及查询中apiAction = :status AND ts between :val1 and :val2" and a filter expression of
的典型范围的大小。您必须在ts
上使用过滤器表达式,所以您应该尝试选择一种解决方案,以最大程度地减少将与关键条件表达式匹配的项的总数,但是同时,您需要了解可以一个分区键(用于表或GSI)的数据量不超过10GB。您还需要记住,只能作为最终一致的读取来查询GSI。
答案 1 :(得分:0)
借助PartiQL SELECT query,您可以有效地执行分区键的查询范围和对排序键应用附加条件。官方 DDB 文档说:
<块引用>确保SELECT语句不会产生全表 扫描,WHERE 子句条件必须指定一个分区键。使用 等式或 IN 运算符。
文档没有特别提到排序键,但它说对非键属性的额外过滤仍然不会导致完整扫描。因此,我几乎可以肯定,带有 supported operators 之一的排序键条件不会导致表扫描、执行速度快并消耗尽可能少的容量单位。
因此您的查询可能如下所示:
SELECT * FROM client_logs WHERE acc_token IN (t1, t2, ...) AND ts BETWEEN t1 AND t2
可以在 here 中找到 PartiQL API 使用的 Node.js 示例。