当前位置: 首页 > 知识库问答 >
问题:

当我们将更多数据放入表中时,DynamodB查询开始花费更多时间

萧飞
2023-03-14

我们有一个具有以下结构的DynamoDb表。

userId - partition key- number
yearOfBirth -attribute number
dateOfBirth - attribute(number in millisecond)
loginTime - attribute(number in millisecond)

再加上GSIuser_gsi

yearOfBirth - partition key- number
dateOfBirth - sort key (number -in millisecond)
loginTime - attribute(number in millisecond)

我们使用java aws sdk查询表。我们的查询要求是在两个出生日期和两个登录时间之间查询所有用户。我们从dateofBirth range获取所有年份,并在单独的线程中查询每个年份,然后将每个线程返回的结果连接起来。

以下代码用于查询出生年份-

public Set<Long> queryForSingleBirthYear(Long startDateDob, Long endDateDob,Long minLoginTime, Long maxLoginTime, int yearOfBirth){
        Set<Long> userIds = new HashSet<>();

        Map<String, AttributeValue> lastEvaluatedKey = null;
        do{
            QueryRequest queryRequest = new QueryRequest().withTableName("user");
            queryRequest
                    .withIndexName("user_gsi")
                    .withExclusiveStartKey(lastEvaluatedKey);

            Condition keyCond = new Condition().withComparisonOperator(ComparisonOperator.EQ)
                    .withAttributeValueList(new AttributeValue().withN(Integer.toString(yearOfBirth)));

            String startDate = startDateDob.toString();
            String endDate = endDateDob.toString();

            Condition dobCond = new Condition().withComparisonOperator(ComparisonOperator.BETWEEN)
                    .withAttributeValueList(new AttributeValue().withN(startDate), new AttributeValue().withN(endDate));

            Map<String, Condition> keyCondMap = new HashMap<>();
            keyCondMap.put("yearOfBirth", keyCond);
            keyCondMap.put("dateOfBirth", dobCond);

            queryRequest.setKeyConditions(keyCondMap);
            Map<String,String> attrNames = new HashMap<>();
            attrNames.put("#loginTime","loginTime");
            Map<String,AttributeValue> attrvalues = new HashMap<>();
            attrvalues.put(":v_minLoginTime",new AttributeValue().withN(minLoginTime.toString()));
            attrvalues.put(":v_maxLoginTime",new AttributeValue().withN(maxLoginTime.toString()));

            String queryFilter = "#loginTime > :v_minLoginTime and #loginTime <= :v_maxLoginTime";

            queryRequest.withFilterExpression(queryFilter)
                    .withExpressionAttributeNames(attrNames)
                    .withExpressionAttributeValues(attrvalues);;

            QueryResult queryResult = amazonDynamoDB.query(queryRequest);
            List<Map<String, AttributeValue>> items = queryResult.getItems();
            for (Map<String, AttributeValue> item : items) {
                String id = item.get("userId").getN();
                userIds.add(Long.valueOf(id));
            }
            lastEvaluatedKey = queryResult.getLastEvaluatedKey();
        }while (lastEvaluatedKey != null);
        return basicFilterRes;
    }

在进行负载测试时,随着我们将更多数据加载到表中,查询开始花费时间。对于20万条记录和大约25年的出生日期范围,大约需要2-3秒。如果我们将表中的记录数增加到150万条,则开始需要大约15-20秒。我们已经尝试增加RCU,甚至将RCU更改为按需模式,但时间保持不变。

编辑

以下是查询每年花费的打印时间后的结果-

yearOfBirth=1972, resultSize=110, timeMs=56
yearOfBirth=1977, resultSize=199, timeMs=54
yearOfBirth=1971, resultSize=89, timeMs=59
yearOfBirth=1973, resultSize=113, timeMs=60
yearOfBirth=1974, resultSize=143, timeMs=60
yearOfBirth=1978, resultSize=266, timeMs=59
yearOfBirth=1998, resultSize=3524, timeMs=612
yearOfBirth=1993, resultSize=3923, timeMs=677
yearOfBirth=1995, resultSize=4569, timeMs=714
yearOfBirth=1994, resultSize=4688, timeMs=777

共有1个答案

潘学民
2023-03-14

loginTime范围是什么?如果它比dateOfBirth范围窄,请考虑将gsi切换为loginTime上的索引。

使用150万记录和25年查询,每个查询将不得不读取大约60,000条记录,这将需要一些时间,因为每个页面都是串行加载的。您可以通过同时查询每年的一部分来并行化每年的查询,方法是将start DateDobendDateDob之间的范围拆分为更小的非重叠范围。例如,如果start DateDob和endDateDob涵盖一整年,则分为12个查询,每个月一个。

 类似资料:
  • 我收集了300万份文件,索引如下: {ts:1},{u\u id:1} 请注意,这是两个单独的升序索引,而不是复合索引。 当我运行此查询时: db.collection.find({u_id:'user'})。排序({ts:-1})。跳过(0)。限制(1) 需要100毫秒。我有以下日志: 2017-04-15T06:42:01.147 0000 I命令[conn783]查询。集合查询:{order

  • 我在学习java stream api时在代码中发现了这个问题。 这是我的代码 我在sts和inteliJ IDE上试用了这段代码,结果都是一样的。并行比顺序需要更长的时间。我的JDK有问题吗?请建议。

  • 任何解决这一问题的建议都将不胜感激。或者我们可以用另一种方式来计数?我想补充一些细节。滑动大小是一个事件和窗口大小超过10小时(每秒大约有300个事件),我们需要对每个事件做出反应。所以在这种情况下,我们没有使用Flink提供的窗口。我们使用来存储前面的信息。在中用于触发旧数据的清理作业。最后dinstinct键的数量非常多。

  • 问题内容: 我正在学习JPA,有一个问题: 在哪些情况下,我们的应用程序需要多个? 我知道的两种情况如下: 当我们的应用程序是多线程应用程序并且一个以上的线程需要JPA事务时,因为它不是线程安全的,因此每个线程需要一个线程。 当任何一个线程需要多个并发事务时,由于和之间存在一对一的关系,因此在该线程中我们需要多个。 Q1。当我们需要多个条件时,还有其他情况吗? Q2。据我了解,每个Percentn

  • 问题内容: 我有一本书得很长。我使用setText()方法在JTextArea中显示它。它冻结了UI,并花费大量时间。我该如何解决? 这是SSCCE: 问题答案: 在与构造GUI分开的单独线程中创建DefaultStyledDocument似乎是创建巨大文本区域的最快方法。DefaultStyledDocument是线程安全的。 这是我用来测试DefaultStyledDocument的代码。我用