我的应用程序与待办事项应用程序相当。在任何给定时间,有几个待处理任务分配给单个用户。有些用户有近2500个待处理的任务,有些只有2个。
当匹配查询的结果低于查询上应用的限制时,似乎数据存储区查询花费的时间太长。例如:
场景1:
用户A:有2500个待处理任务。查询限制为500,第一次请求获取的结果显然为500.所用时间:5767毫秒(5.7秒)。
用户B:有2个待处理任务。查询限制为500,第一次请求获取的结果显然为2.时间:7124毫秒(7.1秒)。
场景2:
用户A:有2500个待处理任务。查询限制为10,第一次请求获取的结果显然为10.所用时间:~400毫秒(1/2秒)。
用户B:有2个待处理任务。查询限制为10,第一次请求获取的结果显然为2.所用时间:5-6秒。
场景3:
用户A:有2500个待处理任务。查询限制为500,第一次请求获取的结果显然为500.所用时间:6244毫秒(6秒)。
用户C:有551个待处理任务。查询限制为500,第一次请求获取的结果显然为500.所用时间:13579毫秒(13秒)。
我的代码:
public static Map <String , Object> getEntitiesUsingQueryCursor( String kind , int limit , int chunkSize , String currentCursor, String account, String user, Boolean status, String dept ) throws Exception
{
String nextCursor = null;
Entity entity = null;
List <Entity> listOfEntity = new ArrayList <Entity>();
Map <String , Object> result = new HashMap <String , Object>();
DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();
com.google.appengine.api.datastore.Query q = new com.google.appengine.api.datastore.Query( kind );
List <Filter> listOfFilter = new ArrayList <Filter>();
Filter filter1 = new FilterPredicate( "account" , FilterOperator.EQUAL , account);
Filter filter2 = new FilterPredicate( "user" , FilterOperator.EQUAL , user);
Filter filter3 = new FilterPredicate( "dept" , FilterOperator.EQUAL , dept);
Filter filter4 = new FilterPredicate( "status" , FilterOperator.EQUAL , status); //Boolean
listOfFilter.add( filter1 );
listOfFilter.add( filter2 );
listOfFilter.add( filter3 );
listOfFilter.add( filter4 );
Filter filterParams1 = filterParams = CompositeFilterOperator.and( listOfFilter );
q.setFilter( filter );
PreparedQuery pq = datastore.prepare( q );
FetchOptions fetchOptions = FetchOptions.Builder.withLimit(limit).prefetchSize( chunkSize ).chunkSize( chunkSize );
if ( !StringUtil.isBlank( currentCursor ) )
fetchOptions.startCursor( Cursor.fromWebSafeString( currentCursor ) );
QueryResultIterable <Entity> results = pq.asQueryResultIterable( fetchOptions );
QueryResultIterator <Entity> iterator = results.iterator();
while ( iterator.hasNext() )
{
entity = iterator.next();
listOfEntity.add( entity );
}
if(listOfEntity.size() == limit)
nextCursor = iterator.getCursor().toWebSafeString();
result.put( "cursor" , nextCursor );
result.put( "entity" , listOfEntity );
return result;
}
这是数据存储区查询的工作原理吗?有人可以提出更好的查询实体的方法吗?如果我在查询上设置了平均限制50,那么少于50个待处理任务的用户必须等待至少7秒才能在页面上完成任务。即使我将限制设置为10并且用户只有2个待处理任务,7秒时间也适用。
答案 0 :(得分:1)
如果您在account,user,dept,status
上定义composite index,则回答上述查询只需要对单个索引进行线性扫描,这样可以大大提高查询速度(无论限制如何)。
为了说明,假设你有
[row] [account, user, dept, status] [entity]
1] A B C D e1
2] A B E F e2
3] A B E F e3
4] A F A A e4
5] B A Z E e5
对'A B E F'
的查询会找到行[2]
,然后线性扫描到[3]
,返回[e1, e2]
。它会在[4]
(不匹配的第一行)停止做很少的工作。