У нас есть таблица 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