You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于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;
  }
}

我想到两种备选方案:

  1. 使用PartiQL:
SELECT * FROM "tableName"."lsiIndexName" WHERE "customerId" = ? and "orderId" in (?, ?, ?);  // 批量50条
  1. 在主索引上执行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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 08:28:10