带与不带FilterExpression的DynamoDB查询RCU消耗差异及优化咨询
一、RCU计算逻辑与异常原因
DynamoDB的读取容量单位(RCU)按实际读取的数据量和一致性级别计算:
- 最终一致性读取:1个RCU可读取最多4KB数据(单条或多条数据总和)
- 强一致性读取:1个RCU对应最多2KB数据
- 无论是否使用
FilterExpression,Query/Scan的RCU消耗都基于过滤前读取的总数据量,而非最终返回的结果量
你遇到的RCU差异,核心原因大概率是分页请求的累计消耗:
- 筛选
isActive=true时,匹配的数据仅4条,DynamoDB会按批次扫描分区内数据,每一批扫描后过滤,若未获取足够结果则发起下一次请求,GUI统计的是所有分页请求的RCU总和,因此数值偏高 - 筛选
isActive=false或全量查询时,大部分数据符合条件,一次请求即可返回全部结果,所以RCU消耗与全量查询一致
此外也存在小概率是一致性级别不一致(比如查询活跃数据用了强一致性,其他查询用最终一致性)或GUI统计包含额外元数据开销,但从你的测试数据来看,分页累计是最主要的原因。
二、低RCU获取活跃数据的优化方法
要降低开销,核心思路是让DynamoDB直接定位目标数据,避免全分区扫描后过滤,以下是三个可行方案:
1. 创建全局二级索引(GSI)
针对isActive属性创建GSI,将分区键设为isActive,排序键使用原表的主键(例如原主键是userId,则设置isActive+userId为GSI的复合主键)。之后查询isActive=true时,直接Query该GSI,只会读取那6条活跃数据,RCU消耗极低——按你的数据计算,6条数据总大小约1.5KB,最终一致性读取仅需0.5个RCU。
创建GSI时可选择KEYS_ONLY或INCLUDE投影模式,只存储必要属性,进一步降低存储和读取开销。唯一额外成本是写入主表时同步写入GSI,但由于活跃数据占比极低,该开销几乎可忽略。
2. 重构主键结构
若允许修改表结构,可将isActive整合到分区键中,例如分区键设为[原PK前缀]#isActive(如USER#true、USER#false)。这样查询活跃数据时直接指定分区键USER#true,无需过滤,RCU仅计算目标数据的量,效率最高。
3. 使用稀疏索引优化
因为isActive=true的数据占比极低,可创建稀疏GSI:仅当isActive=true时,该数据才会被写入GSI。操作时将GSI的分区键设为isActive,并设置GSI只包含你需要的属性。这样GSI中仅存在活跃数据,Query该索引可直接获取所有目标结果,彻底避免扫描无关数据。
补充说明
你最初的理解是正确的:基于PK的Query确实先读取全分区数据再过滤,理论上RCU应与全量查询一致,实际差异是工具统计分页请求累计导致的。通过上述索引优化方案,可彻底解决RCU消耗过高的问题。
内容的提问来源于stack exchange,提问作者Cabbage_Lower

