Запрос DynamodB начинает занимать больше времени, когда мы помещаем больше данных в таблицу - PullRequest
1 голос
/ 26 марта 2019

У нас есть таблица DynamoDb со следующей структурой.

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

и со следующим gsi - user_gsi

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

мы используем java aws sdk для запроса таблицы. Наше требование состоит в том, чтобы запросить всех пользователей между двумя dateOfBirth и двумя loginTime. Мы получаем весь год из диапазона dateofBirth и запрашиваем каждый год в отдельном потоке, а затем объединяем результат, возвращаемый каждым потоком.

Следующий код используется для запроса за один годOfBirth-

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

Во время нашего нагрузочного тестирования наши запросы начинают занимать время, так как мы загружаем больше данных в таблицу. Для записей 200K и около, а также для диапазона dateOfBirth, имеющего около 25 yearFfirth, это занимает приблизительно 2-3 секунды. Если мы увеличим количество записей в таблице до 1,5 миллионов, это займет около 15-20 секунд. Мы пытались увеличить RCU и даже переключить RCU в режим по требованию, но время остается тем же.

EDIT

Ниже приведены результаты после печати, взятые по запросу для каждого года-

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 Ответ

1 голос
/ 26 марта 2019

Что такое диапазон loginTime?Попробуйте переключить gsi в index для loginTime, если он уже, чем диапазон dateOfBirth.

С 1,5 миллионами записей и 25-летними запросами каждый запрос должен будет прочитать около 60 000 записей, что займет некоторое время, так как каждая страницазагружен серийно.Вы можете распараллеливать каждый год запрос, запрашивая часть каждого года одновременно, разбивая диапазон между startDateDob и endDateDob на меньшие непересекающиеся диапазоны.например, если startDateDob и endDateDob охватывают целый год, разбитый на 12 запросов, по одному на каждый месяц.

...