基于LSI排序键批量检索DDB条目的高性价比方案咨询
问题背景
我有如下结构的DynamoDB表:
| CustomerID (PK) | emailId (SortKey) | orderId (LSI) |
|---|
需要用AWS DynamoDB Java SDK实现两种批量检索模式:
- 按单个PK+50个emailId(SK)批量获取条目
- 按单个PK+50个orderId(LSI排序键)批量获取条目
第一种模式已通过以下代码实现:
ReadBatch.Builder<Customer> customerBuilder = ReadBatch.builder(Customer.class) .mappedTableResource(customerTable); emails.forEach(email -> { Customer key = new Customer(); key.setCustomerId(custId); key.setEmail(email); customerBuilder.addGetItem(key); }); BatchGetItemEnhancedRequest batchGetItemEnhancedRequest = BatchGetItemEnhancedRequest.builder() .addReadBatch(customerBuilder.build()) .build();
但尝试用LSI排序键orderId执行相同操作时,请求返回400错误,且找不到设置LSI索引名称的API,修改后的代码如下:
orderIds.forEach(orderId -> { Customer key = new Customer(); key.setCustomerId(custId); key.setOrderId(orderId); customerBuilder.addGetItem(key); }); BatchGetItemEnhancedRequest batchGetItemEnhancedRequest = BatchGetItemEnhancedRequest.builder() .addReadBatch(customerBuilder.build()) .build();
Customer表实体类代码:
@DynamoDbBean @Getter @Setter public class Customer { private String customerId; private String emailId; private String orderId; @DynamoDbPartitionKey @DynamoDbAttribute("customerId") public String getCustomerId() { return customerId; } @DynamoDbSortKey @DynamoDbAttribute("emailId") public String getEmailId() { return emailId; } @DynamoDbSecondarySortKey(indexNames = {"orderId-index"}) public String getOrderId() { return orderId; } }
我想到两种备选方案:
- 使用PartiQL:
SELECT * FROM "tableName"."lsiIndexName" WHERE "customerId" = ? and "orderId" in (?, ?, ?); // 批量50条
- 在主索引上执行Query并使用过滤表达式:
String keyConditionExpression = "#customerId" + " = :partitionKeyVal"; String filterExpression = "#orderId" + " IN (:value1, :value2, :value, :value)"; // 遗憾的是无法针对LSI执行查询,因为SDK不允许对多个排序键使用过滤表达式 QueryRequest queryRequest = QueryRequest.builder() .tableName("customer") .keyConditionExpression(keyConditionExpression) .filterExpression(filterExpression) .expressionAttributeNames(expressionAttributeNames) .expressionAttributeValues(expressionAttributeValues) .build();
考虑到每个分区可能有2万+条目,从成本和性能角度,哪种方式是检索LSI排序键批量条目的最优方案?
最优方案分析
从成本和性能维度对比两个方案,PartiQL查询LSI的方案是最优选择,原因如下:
性能层面
- PartiQL查询LSI:LSI的结构是
customerId(PK)+orderId(SK),你的查询条件完全匹配LSI的主键结构,DynamoDB可以直接通过索引精准定位目标条目,延迟极低,返回的就是需要的50条数据,无需额外处理。 - 主索引Query+过滤表达式:该方式会先扫描当前PK下的全部2万+条数据,再在内存中过滤出符合
orderId条件的条目。随着分区数据量增大,查询延迟会显著上升,且如果目标条目占比低,会做大量无用扫描,性能极差。
成本层面
DynamoDB的读取成本按实际读取的数据量计算:
- PartiQL查询LSI:仅读取目标50条数据,消耗的读取容量单位(RCU)仅对应这50条数据的大小,成本极低。
- 主索引Query+过滤表达式:需要读取当前PK下的所有2万+条数据,消耗的RCU是2万+条数据的总大小,成本是前者的数百倍,完全不划算。
补充说明
BatchGetItem无法用于LSI的原因是,该API仅支持针对表的主索引(主键)进行批量获取,不支持二级索引。而PartiQL支持直接查询LSI,正好适配你的批量查询需求,是完全可行的方案。
内容的提问来源于stack exchange,提问作者Govinda Sakhare
相关产品推荐
相关产品推荐

