我正在本地分析我的应用程序(使用Dev服务器)以获取有关GAE如何工作的更多信息。我的测试是比较常见的完整实体查询和投影查询。在我的测试中,两个查询都执行相同的查询,但Projection指定了2个属性。测试类具有100个属性,每个实体具有相同的值,总共10个实体。下面显示了使用数据存储区查看器和Appstats生成的数据的图像。在Appstats映像中,Request 4是一个memcache flush,Request 3是测试数据库创建(它已经创建,所以这里没有成本),Request 2是完整的Entity查询,Request 1是投影查询。
我很惊讶两个查询都导致相同数量的读取。我的猜测是小型和读取操作,并由Appstats报告相同。如果是这种情况,我想在报告中将它们分开。这是与查询相关的功能:
// Full Entity Query
public ReturnCodes doQuery() {
DatastoreService dataStore = DatastoreServiceFactory.getDatastoreService();
for(int i = 0; i < numIters; ++i) {
Filter filter = new FilterPredicate(DBCreation.PROPERTY_NAME_PREFIX + i,
FilterOperator.NOT_EQUAL, i);
Query query = new Query(DBCreation.ENTITY_NAME).setFilter(filter);
PreparedQuery prepQuery = dataStore.prepare(query);
Iterable<Entity> results = prepQuery.asIterable();
for(Entity result : results) {
log.info(result.toString());
}
}
return ReturnCodes.SUCCESS;
}
// Projection Query
public ReturnCodes doQuery() {
DatastoreService dataStore = DatastoreServiceFactory.getDatastoreService();
for(int i = 0; i < numIters; ++i) {
String projectionPropName = DBCreation.PROPERTY_NAME_PREFIX + i;
Filter filter = new FilterPredicate(DBCreation.PROPERTY_NAME_PREFIX + i,
FilterOperator.NOT_EQUAL, i);
Query query = new Query(DBCreation.ENTITY_NAME).setFilter(filter);
query.addProjection(new PropertyProjection(DBCreation.PROPERTY_NAME_PREFIX + 0, Integer.class));
query.addProjection(new PropertyProjection(DBCreation.PROPERTY_NAME_PREFIX + 1, Integer.class));
PreparedQuery prepQuery = dataStore.prepare(query);
Iterable<Entity> results = prepQuery.asIterable();
for(Entity result : results) {
log.info(result.toString());
}
}
return ReturnCodes.SUCCESS;
}
有什么想法吗?
编辑:为了更好地概述问题,我创建了另一个测试,它执行相同的查询但仅使用密钥查询。对于这种情况,Appstats正在报告中正确显示DATASTORE_SMALL操作。我仍然对投影查询的行为感到困惑,它也应该报告DATASTORE_SMALL操作。请帮忙!
答案 0 :(得分:1)
[我写了appstats的go端口,所以这是基于我的经验和回忆。]
我猜这是appstats中的一个错误,这是一个相对不受维护的程序。投影查询是新的,因此appstats可能不会意识到它们,并将它们视为正常的读取查询。
对于某些背景,计算成本很困难。对于写操作,成本与结果一起返回,因为它们必须是,因为应用程序无法知道更改的内容(这是写入成本发生的位置)。但是,对于读取和小操作,有formula来计算成本。每个appstats实现(python,java,go)都必须实现此计算,包括反射或请求对象所需的任何内容,以确定发生了什么。用于执行此操作的API并不完全明显,并且有很多小事情,因此很容易弄错,并且很难将其弄好。