DynamoDBMapper提供了从表中读取一项的不同方法:
- 查询
- <
- 负载/gh>
是否有建议,使用哪一个?在一个快速测试中,以下两个代码片段为一个主键=hash和范围键=date的表返回相同的"MyEntry"项,而查询方法大约快10%。
<负载/strong>
public MyEntry getEntryForDay(final Integer hash, final LocalDate date) {
return mapper.load(MyEntry.class, hash, date);
}
查询
public MyEntry getEntryForDay(final Integer hash, final LocalDate date) {
final MyEntry hashKeyValues = new MyEntry ();
hashKeyValues.setHash(hash);
final Condition rangeKeyCondition = new Condition()//
.withComparisonOperator(ComparisonOperator.EQ.toString())//
.withAttributeValueList(new AttributeValue().withS(new LocalDateMarshaller().marshall(date)));
final DynamoDBQueryExpression<MyEntry> queryExpression = new DynamoDBQueryExpression<MyEntry>()//
.withHashKeyValues(hashKeyValues)//
.withRangeKeyCondition("date", rangeKeyCondition)//
.withLimit(1);
final List<MyEntry> storedEntries = mapper
.query(MyEntry.class, queryExpression);
if (storedEntries.size() == 0) {
return null;
}
return storedEntries.get(0);
}
载入和查询是不同的操作:
如果你有一个只有哈希键的模式,它们会执行相同的操作——用指定的哈希键检索项目。
如果您有一个散列范围模式,load检索由单个散列+范围对标识的特定项。查询检索具有指定哈希键且满足范围键条件的所有项。
由于您对哈希键和范围键都使用了相等运算符,因此操作是完全相等的。
好了,现在我越来越习惯使用DynamoDB,结果发现映射器中的一个bug。查询代码导致性能下降:
- "withLimit(1)"实际上并没有限制列表中返回的总结果,而是将结果返回到"PaginatedQueryList"中,如果访问,实际项目将从DB惰性加载。WithLimit(1)实际上限制了每个请求加载的项目。
- 实际的bug是部分"if (storedEntries.size() == 0)",因为size()调用实际上加载列表中的所有项目。使用withLimit(1)将导致最差的性能。
mapper查询的正确代码是:
public MyEntry getEntryForDay(final Integer hash, final LocalDate date) {
final MyEntry hashKeyValues = new MyEntry ();
hashKeyValues.setHash(hash);
final Condition rangeKeyCondition = new Condition()//
.withComparisonOperator(ComparisonOperator.EQ.toString())//
.withAttributeValueList(new AttributeValue().withS(new LocalDateMarshaller().marshall(date)));
final DynamoDBQueryExpression<MyEntry> queryExpression = new DynamoDBQueryExpression<MyEntry>()//
.withHashKeyValues(hashKeyValues)//
.withRangeKeyCondition("date", rangeKeyCondition)//
.withLimit(1);
final List<MyEntry> storedEntries = mapper
.query(MyEntry.class, queryExpression);
if (storedEntries.isEmpty()) {
return null;
}
return storedEntries.get(0);
}