繁体   English   中英

DynamoDb 扫描过滤器不返回某些请求的结果

[英]DynamoDb scan filter not returning results for some requests

我有一个包含两列 FirstId 和 SecondId 的表。 FirstId 是主键,而 SecondId 未编入索引

FirstId |  SecondId    
--------------------
  abc   |  123     
  xyz   |  789     

我正在执行扫描过滤器以使用 JavaSDK 从 SecondId 获取 FirstId 值。 我有大约 12k 个条目,并且运行良好。 最近,扫描请求在某些情况下开始返回null ,但我可以在 AWS UI 中找到该条目

这是我的代码

    Condition scanFilterCondition = new Condition()
        .withComparisonOperator(ComparisonOperator.EQ)
        .withAttributeValueList(new AttributeValue().withS(secondIdValue));
    
    Map<String, Condition> conditions = new HashMap<String, Condition>();
    conditions.put("SecondId", scanFilterCondition);

    ScanRequest scanRequest = new ScanRequest()
            .withTableName(table)
            .withScanFilter(conditions);
    
    ScanResult result = mDBClient.scan(scanRequest);
    if(result.getItems().size() == 0) {
        return null;
    }
        
    Map<String, AttributeValue> item = result.getItems().get(0);
    
    return item.get("FirstId").getS();

我假设这可能是因为随着数据的增长,操作变得越来越昂贵! 有没有办法优化这个请求? 或者,有什么我想念的吗?

您的问题可能通过了解 DynamoDB 如何处理扫描、过滤器和分页来解释。

要记住的几件事:

  • 每次scan最多只能读取 1MB 的数据
  • scan (或query应用过滤操作
  • 扫描将搜索整个数据库

考虑到这些因素,在找到(或未找到)您要查找的数据之前,您可能需要对几个空的扫描结果进行分页。 您可能正在读取完整的 1MB 数据,将其全部过滤掉,然后向客户端返回一个空结果集。 result.getItems().size()可能为零,但这并不意味着您不必执行另一个scan操作来完成搜索。

我不确定这是您的问题,但很容易验证。 如果scan操作正在分页,DDB 将返回一个包含scan结果的字段LastEvaluatedKey 如果是这样,您将需要发出另一个scan请求以继续scan操作。

同样,这可能不是您的问题,但它可以解释为什么您没有看到从单次scan操作中获得的结果。

我与 AWS 支持工程师进行了长时间的调试会话,但我们仍然无法找出原因。 AWS CLI 和 UI 都返回了结果,但没有返回 JAVA SDK 扫描查询。

因此,我为SecondId创建了一个 GSI 并更改了我的代码以执行索引查询而不是扫描查询,它为我解决了问题。

    Table table = dynamoDB.getTable(table);
    Index index = table.getIndex("SecondId-index");

    QuerySpec spec = new QuerySpec()
            .withKeyConditionExpression("SecondId = :second_id")
            .withValueMap( new ValueMap()
                .withString(":second_id", secondIdValue));

    ItemCollection<QueryOutcome> items = index.query(spec);

    if(!items.iterator().hasNext()) {
        return null;
    }
    
    JsonNode result = jsonMapper.readTree(items.iterator().next().toJSON());

    return result.get("FirstId").asText();

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM